Dashboard sipadu mbip
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

aui-node-html5-print.js 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. AUI.add('aui-node-html5-print', function(A) {
  2. var CONFIG = A.config,
  3. DOC = CONFIG.doc,
  4. WIN = CONFIG.win,
  5. UA = A.UA,
  6. IE = UA.ie,
  7. isShivDisabled = function() {
  8. return WIN.AUI_HTML5_IE === false;
  9. };
  10. if (!IE || IE >= 9 || isShivDisabled()) {
  11. return;
  12. }
  13. var BUFFER_CSS_TEXT = [],
  14. CSS_PRINTFIX = 'aui-printfix',
  15. CSS_PRINTFIX_PREFIX = 'aui-printfix-',
  16. LOCATION = WIN.location,
  17. DOMAIN = LOCATION.protocol + '//' + LOCATION.host,
  18. GLOBAL_AUI = YUI.AUI,
  19. HTML = DOC.documentElement,
  20. HTML5_ELEMENTS = GLOBAL_AUI.HTML5_ELEMENTS,
  21. HTML5_ELEMENTS_LENGTH = HTML5_ELEMENTS.length,
  22. HTML5_ELEMENTS_LIST = HTML5_ELEMENTS.join('|'),
  23. REGEX_CLONE_NODE_CLEANUP = new RegExp('<(/?):(' + HTML5_ELEMENTS_LIST + ')', 'gi'),
  24. REGEX_ELEMENTS = new RegExp('(' + HTML5_ELEMENTS_LIST + ')', 'gi'),
  25. REGEX_ELEMENTS_FAST = new RegExp('\\b(' + HTML5_ELEMENTS_LIST + ')\\b', 'i'),
  26. REGEX_PRINT_MEDIA = /print|all/,
  27. REGEX_RULE = new RegExp('(^|[^\\n{}]*?\\s)(' + HTML5_ELEMENTS_LIST + ').*?{([^}]*)}', 'gim'),
  28. REGEX_TAG = new RegExp('<(\/*)(' + HTML5_ELEMENTS_LIST + ')', 'gi'),
  29. SELECTOR_REPLACE_RULE = '.' + CSS_PRINTFIX_PREFIX + '$1',
  30. STR_ALL = 'all',
  31. STR_BLANK = ' ',
  32. STR_EMPTY = '',
  33. STR_BRACKET_OPEN = '{',
  34. STR_BRACKET_CLOSE = '}',
  35. STR_CHECKBOX = 'checkbox',
  36. STR_CHECKED = 'checked',
  37. STR_HTTPS = 'https',
  38. STR_IFRAME = 'IFRAME',
  39. STR_INPUT = 'INPUT',
  40. STR_OPTION = 'OPTION',
  41. STR_RADIO = 'radio',
  42. STR_SELECTED = 'selected',
  43. STR_STAR = '*',
  44. STR_URL = 'url(',
  45. STR_URL_DOMAIN = STR_URL + DOMAIN,
  46. TAG_REPLACE_ORIGINAL = '<$1$2',
  47. TAG_REPLACE_FONT = '<$1font';
  48. var html5shiv = GLOBAL_AUI.html5shiv,
  49. // Yes, IE does this wackiness; converting an object
  50. // to a string should never result in undefined, but
  51. // IE's styleSheet object sometimes becomes inaccessible
  52. // after trying to print the second time
  53. isStylesheetDefined = function(obj) {
  54. return obj && (obj + STR_EMPTY !== undefined);
  55. },
  56. toggleNode = function(node, origNode, prop) {
  57. var state = origNode[prop];
  58. if (state) {
  59. node.setAttribute(prop, state);
  60. }
  61. else {
  62. node.removeAttribute(prop);
  63. }
  64. };
  65. html5shiv(DOC);
  66. var PrintFix = function() {
  67. var afterPrint = function() {
  68. if (isShivDisabled()) {
  69. destroy();
  70. }
  71. else {
  72. PrintFix.onAfterPrint();
  73. }
  74. };
  75. var beforePrint = function() {
  76. if (isShivDisabled()) {
  77. destroy();
  78. }
  79. else {
  80. PrintFix.onBeforePrint();
  81. }
  82. };
  83. var destroy = function() {
  84. WIN.detachEvent('onafterprint', afterPrint);
  85. WIN.detachEvent('onbeforeprint', beforePrint);
  86. };
  87. var init = function() {
  88. WIN.attachEvent('onafterprint', afterPrint);
  89. WIN.attachEvent('onbeforeprint', beforePrint);
  90. };
  91. init();
  92. PrintFix.destroy = destroy;
  93. PrintFix.init = init;
  94. };
  95. A.mix(
  96. PrintFix,
  97. {
  98. onAfterPrint: function() {
  99. var instance = this;
  100. instance.restoreHTML();
  101. var styleSheet = instance._getStyleSheet();
  102. styleSheet.styleSheet.cssText = STR_EMPTY;
  103. },
  104. onBeforePrint: function() {
  105. var instance = this;
  106. var styleSheet = instance._getStyleSheet();
  107. var cssRules = instance._getAllCSSText();
  108. styleSheet.styleSheet.cssText = instance.parseCSS(cssRules);
  109. instance.writeHTML();
  110. },
  111. parseCSS: function(cssText) {
  112. var instance = this;
  113. var css = STR_EMPTY;
  114. var rules = cssText.match(REGEX_RULE);
  115. if (rules) {
  116. css = rules.join('\n').replace(REGEX_ELEMENTS, SELECTOR_REPLACE_RULE);
  117. }
  118. return css;
  119. },
  120. restoreHTML: function() {
  121. var instance = this;
  122. var bodyClone = instance._getBodyClone();
  123. var bodyEl = instance._getBodyEl();
  124. var newNodes = bodyClone.getElementsByTagName(STR_IFRAME);
  125. var originalNodes = bodyEl.getElementsByTagName(STR_IFRAME);
  126. var length = originalNodes.length;
  127. // Moving IFRAME nodes back to their original position
  128. if (length == newNodes.length) {
  129. while (length--) {
  130. var newNode = newNodes[length];
  131. var originalNode = originalNodes[length];
  132. originalNode.swapNode(newNode);
  133. }
  134. }
  135. bodyClone.innerHTML = STR_EMPTY;
  136. HTML.removeChild(bodyClone);
  137. HTML.appendChild(bodyEl);
  138. },
  139. writeHTML: function() {
  140. var instance = this;
  141. var i = -1;
  142. var j;
  143. var bodyEl = instance._getBodyEl();
  144. var html5Element;
  145. var cssClass;
  146. var nodeList;
  147. var nodeListLength;
  148. var node;
  149. var buffer = [];
  150. while (++i < HTML5_ELEMENTS_LENGTH) {
  151. html5Element = HTML5_ELEMENTS[i];
  152. nodeList = DOC.getElementsByTagName(html5Element);
  153. nodeListLength = nodeList.length;
  154. j = -1;
  155. while (++j < nodeListLength) {
  156. node = nodeList[j];
  157. cssClass = node.className;
  158. if (cssClass.indexOf(CSS_PRINTFIX_PREFIX) == -1) {
  159. buffer[0] = CSS_PRINTFIX_PREFIX + html5Element;
  160. buffer[1] = cssClass;
  161. node.className = buffer.join(STR_BLANK);
  162. }
  163. }
  164. }
  165. var docFrag = instance._getDocFrag();
  166. var bodyClone = instance._getBodyClone();
  167. docFrag.appendChild(bodyEl);
  168. HTML.appendChild(bodyClone);
  169. bodyClone.className = bodyEl.className;
  170. bodyClone.id = bodyEl.id;
  171. var originalNodes = bodyEl.getElementsByTagName(STR_STAR);
  172. var length = originalNodes.length;
  173. // IE will throw a mixed content warning when using https
  174. // and calling clone node if the body contains elements with
  175. // an inline background-image style that is relative to the domain.
  176. if (UA.secure) {
  177. var bodyElStyle = bodyEl.style;
  178. var elStyle;
  179. var backgroundImage;
  180. bodyElStyle.display = 'none';
  181. for (i = 0; i < length; i++) {
  182. elStyle = originalNodes[i].style;
  183. backgroundImage = elStyle.backgroundImage;
  184. if (backgroundImage &&
  185. backgroundImage.indexOf(STR_URL) > -1 &&
  186. backgroundImage.indexOf(STR_HTTPS) == -1) {
  187. elStyle.backgroundImage = backgroundImage.replace(STR_URL, STR_URL_DOMAIN);
  188. }
  189. }
  190. bodyElStyle.display = STR_EMPTY;
  191. }
  192. var bodyElClone = bodyEl.cloneNode(true);
  193. var newNodes = bodyElClone.getElementsByTagName(STR_STAR);
  194. if (length == newNodes.length) {
  195. while (length--) {
  196. var newNode = newNodes[length];
  197. var newNodeName = newNode.nodeName;
  198. if (newNodeName == STR_INPUT || newNodeName == STR_OPTION || newNodeName == STR_IFRAME) {
  199. var originalNode = originalNodes[length];
  200. var originalNodeName = originalNode.nodeName;
  201. if (originalNodeName == newNodeName) {
  202. var prop = null;
  203. if (newNodeName == STR_OPTION) {
  204. prop = STR_SELECTED;
  205. }
  206. else if (newNodeName == STR_INPUT && (newNode.type == STR_CHECKBOX || newNode.type == STR_RADIO)) {
  207. prop = STR_CHECKED;
  208. }
  209. else if (newNodeName == STR_IFRAME) {
  210. newNode.src = STR_EMPTY;
  211. }
  212. if (prop !== null) {
  213. toggleNode(newNode, originalNode, prop);
  214. }
  215. }
  216. }
  217. }
  218. }
  219. var bodyHTML = bodyElClone.innerHTML;
  220. bodyHTML = bodyHTML.replace(REGEX_CLONE_NODE_CLEANUP, TAG_REPLACE_ORIGINAL).replace(REGEX_TAG, TAG_REPLACE_FONT);
  221. bodyClone.innerHTML = bodyHTML;
  222. // Post processing the DOM in order to move IFRAME nodes
  223. newNodes = bodyClone.getElementsByTagName(STR_IFRAME);
  224. originalNodes = bodyEl.getElementsByTagName(STR_IFRAME);
  225. length = originalNodes.length;
  226. if (length == newNodes.length) {
  227. while (length--) {
  228. var newNode = newNodes[length];
  229. var originalNode = originalNodes[length];
  230. // According to quirksmode.org, swapNode is supported on all major IE versions
  231. originalNode.swapNode(newNode);
  232. }
  233. }
  234. },
  235. _getAllCSSText: function() {
  236. var instance = this;
  237. var buffer = [];
  238. var styleSheets = instance._getAllStyleSheets(DOC.styleSheets, STR_ALL);
  239. var rule;
  240. var cssText;
  241. for (var i = 0; styleSheet = styleSheets[i]; i++) {
  242. var rules = styleSheet.rules;
  243. if (rules && rules.length) {
  244. for (var j = 0, ruleLength = rules.length; j < ruleLength; j++) {
  245. rule = rules[j];
  246. if (!rule.href) {
  247. cssText = instance._getCSSTextFromRule(rule);
  248. buffer.push(cssText);
  249. }
  250. }
  251. }
  252. }
  253. return buffer.join(STR_BLANK);
  254. },
  255. _getCSSTextFromRule: function(rule) {
  256. var instance = this;
  257. var cssText = STR_EMPTY;
  258. var ruleStyle = rule.style;
  259. var ruleCSSText;
  260. var ruleSelectorText;
  261. if (ruleStyle && (ruleCSSText = ruleStyle.cssText) && (ruleSelectorText = rule.selectorText) && REGEX_ELEMENTS_FAST.test(ruleSelectorText)) {
  262. BUFFER_CSS_TEXT.length = 0;
  263. BUFFER_CSS_TEXT.push(ruleSelectorText, STR_BRACKET_OPEN, ruleCSSText, STR_BRACKET_CLOSE);
  264. cssText = BUFFER_CSS_TEXT.join(STR_BLANK);
  265. }
  266. return cssText;
  267. },
  268. _getAllStyleSheets: function(styleSheet, mediaType, level, buffer) {
  269. var instance = this;
  270. level = level || 1;
  271. buffer = buffer || [];
  272. var i;
  273. if (isStylesheetDefined(styleSheet)) {
  274. var imports = styleSheet.imports;
  275. mediaType = styleSheet.mediaType || mediaType;
  276. if (REGEX_PRINT_MEDIA.test(mediaType)) {
  277. var length;
  278. // IE can crash when trying to access imports more than 3 levels deep
  279. if (level <= 3 && isStylesheetDefined(imports) && imports.length) {
  280. for (i = 0, length = imports.length; i < length; i++) {
  281. instance._getAllStyleSheets(imports[i], mediaType, level + 1, buffer);
  282. }
  283. }
  284. else if (styleSheet.length) {
  285. for (i = 0, length = styleSheet.length; i < length; i++) {
  286. instance._getAllStyleSheets(styleSheet[i], mediaType, level, buffer);
  287. }
  288. }
  289. else {
  290. var rules = styleSheet.rules;
  291. var ruleStyleSheet;
  292. if (rules && rules.length) {
  293. for (i = 0, length = rules.length; i < length; i++) {
  294. ruleStyleSheet = rules[i].styleSheet;
  295. if (ruleStyleSheet) {
  296. instance._getAllStyleSheets(ruleStyleSheet, mediaType, level, buffer);
  297. }
  298. }
  299. }
  300. }
  301. if (!styleSheet.disabled && styleSheet.rules) {
  302. buffer.push(styleSheet);
  303. }
  304. }
  305. }
  306. mediaType = STR_ALL;
  307. return buffer;
  308. },
  309. _getBodyEl: function() {
  310. var instance = this;
  311. var bodyEl = instance._bodyEl;
  312. if (!bodyEl) {
  313. bodyEl = DOC.body;
  314. instance._bodyEl = bodyEl;
  315. }
  316. return bodyEl;
  317. },
  318. _getBodyClone: function() {
  319. var instance = this;
  320. var bodyClone = instance._bodyClone;
  321. if (!bodyClone) {
  322. bodyClone = DOC.createElement('body');
  323. instance._bodyClone = bodyClone;
  324. }
  325. return bodyClone;
  326. },
  327. _getDocFrag: function() {
  328. var instance = this;
  329. var docFrag = instance._docFrag;
  330. if (!docFrag) {
  331. docFrag = DOC.createDocumentFragment();
  332. html5shiv(docFrag);
  333. instance._docFrag = docFrag;
  334. }
  335. return docFrag;
  336. },
  337. _getStyleSheet: function() {
  338. var instance = this;
  339. var styleSheet = instance._styleSheet;
  340. if (!styleSheet) {
  341. styleSheet = DOC.createElement('style');
  342. var head = DOC.documentElement.firstChild;
  343. head.insertBefore(styleSheet, head.firstChild);
  344. styleSheet.media = 'print';
  345. styleSheet.className = CSS_PRINTFIX;
  346. instance._styleSheet = styleSheet;
  347. }
  348. return styleSheet;
  349. }
  350. }
  351. );
  352. A.namespace('HTML5').PrintFix = PrintFix;
  353. PrintFix();
  354. }, '@VERSION@' ,{requires:['aui-node-html5']});