Helper.html 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-DomHelper'>/**
  19. </span> * @class Ext.DomHelper
  20. * @extends Ext.dom.Helper
  21. * @alternateClassName Ext.core.DomHelper
  22. * @singleton
  23. *
  24. * The DomHelper class provides a layer of abstraction from DOM and transparently supports creating elements via DOM or
  25. * using HTML fragments. It also has the ability to create HTML fragment templates from your DOM building code.
  26. *
  27. * # DomHelper element specification object
  28. *
  29. * A specification object is used when creating elements. Attributes of this object are assumed to be element
  30. * attributes, except for 4 special attributes:
  31. *
  32. * - **tag** - The tag name of the element.
  33. * - **children** or **cn** - An array of the same kind of element definition objects to be created and appended.
  34. * These can be nested as deep as you want.
  35. * - **cls** - The class attribute of the element. This will end up being either the &quot;class&quot; attribute on a HTML
  36. * fragment or className for a DOM node, depending on whether DomHelper is using fragments or DOM.
  37. * - **html** - The innerHTML for the element.
  38. *
  39. * **NOTE:** For other arbitrary attributes, the value will currently **not** be automatically HTML-escaped prior to
  40. * building the element's HTML string. This means that if your attribute value contains special characters that would
  41. * not normally be allowed in a double-quoted attribute value, you **must** manually HTML-encode it beforehand (see
  42. * {@link Ext.String#htmlEncode}) or risk malformed HTML being created. This behavior may change in a future release.
  43. *
  44. * # Insertion methods
  45. *
  46. * Commonly used insertion methods:
  47. *
  48. * - **{@link #append}**
  49. * - **{@link #insertBefore}**
  50. * - **{@link #insertAfter}**
  51. * - **{@link #overwrite}**
  52. * - **{@link #createTemplate}**
  53. * - **{@link #insertHtml}**
  54. *
  55. * # Example
  56. *
  57. * This is an example, where an unordered list with 3 children items is appended to an existing element with
  58. * id 'my-div':
  59. *
  60. * var dh = Ext.DomHelper; // create shorthand alias
  61. * // specification object
  62. * var spec = {
  63. * id: 'my-ul',
  64. * tag: 'ul',
  65. * cls: 'my-list',
  66. * // append children after creating
  67. * children: [ // may also specify 'cn' instead of 'children'
  68. * {tag: 'li', id: 'item0', html: 'List Item 0'},
  69. * {tag: 'li', id: 'item1', html: 'List Item 1'},
  70. * {tag: 'li', id: 'item2', html: 'List Item 2'}
  71. * ]
  72. * };
  73. * var list = dh.append(
  74. * 'my-div', // the context element 'my-div' can either be the id or the actual node
  75. * spec // the specification object
  76. * );
  77. *
  78. * Element creation specification parameters in this class may also be passed as an Array of specification objects. This
  79. * can be used to insert multiple sibling nodes into an existing container very efficiently. For example, to add more
  80. * list items to the example above:
  81. *
  82. * dh.append('my-ul', [
  83. * {tag: 'li', id: 'item3', html: 'List Item 3'},
  84. * {tag: 'li', id: 'item4', html: 'List Item 4'}
  85. * ]);
  86. *
  87. * # Templating
  88. *
  89. * The real power is in the built-in templating. Instead of creating or appending any elements, {@link #createTemplate}
  90. * returns a Template object which can be used over and over to insert new elements. Revisiting the example above, we
  91. * could utilize templating this time:
  92. *
  93. * // create the node
  94. * var list = dh.append('my-div', {tag: 'ul', cls: 'my-list'});
  95. * // get template
  96. * var tpl = dh.createTemplate({tag: 'li', id: 'item{0}', html: 'List Item {0}'});
  97. *
  98. * for(var i = 0; i &lt; 5, i++){
  99. * tpl.append(list, [i]); // use template to append to the actual node
  100. * }
  101. *
  102. * An example using a template:
  103. *
  104. * var html = '&lt;a id=&quot;{0}&quot; href=&quot;{1}&quot; class=&quot;nav&quot;&gt;{2}&lt;/a&gt;';
  105. *
  106. * var tpl = new Ext.DomHelper.createTemplate(html);
  107. * tpl.append('blog-roll', ['link1', 'http://www.edspencer.net/', &quot;Ed's Site&quot;]);
  108. * tpl.append('blog-roll', ['link2', 'http://www.dustindiaz.com/', &quot;Dustin's Site&quot;]);
  109. *
  110. * The same example using named parameters:
  111. *
  112. * var html = '&lt;a id=&quot;{id}&quot; href=&quot;{url}&quot; class=&quot;nav&quot;&gt;{text}&lt;/a&gt;';
  113. *
  114. * var tpl = new Ext.DomHelper.createTemplate(html);
  115. * tpl.append('blog-roll', {
  116. * id: 'link1',
  117. * url: 'http://www.edspencer.net/',
  118. * text: &quot;Ed's Site&quot;
  119. * });
  120. * tpl.append('blog-roll', {
  121. * id: 'link2',
  122. * url: 'http://www.dustindiaz.com/',
  123. * text: &quot;Dustin's Site&quot;
  124. * });
  125. *
  126. * # Compiling Templates
  127. *
  128. * Templates are applied using regular expressions. The performance is great, but if you are adding a bunch of DOM
  129. * elements using the same template, you can increase performance even further by {@link Ext.Template#compile
  130. * &quot;compiling&quot;} the template. The way &quot;{@link Ext.Template#compile compile()}&quot; works is the template is parsed and
  131. * broken up at the different variable points and a dynamic function is created and eval'ed. The generated function
  132. * performs string concatenation of these parts and the passed variables instead of using regular expressions.
  133. *
  134. * var html = '&lt;a id=&quot;{id}&quot; href=&quot;{url}&quot; class=&quot;nav&quot;&gt;{text}&lt;/a&gt;';
  135. *
  136. * var tpl = new Ext.DomHelper.createTemplate(html);
  137. * tpl.compile();
  138. *
  139. * //... use template like normal
  140. *
  141. * # Performance Boost
  142. *
  143. * DomHelper will transparently create HTML fragments when it can. Using HTML fragments instead of DOM can significantly
  144. * boost performance.
  145. *
  146. * Element creation specification parameters may also be strings. If {@link #useDom} is false, then the string is used
  147. * as innerHTML. If {@link #useDom} is true, a string specification results in the creation of a text node. Usage:
  148. *
  149. * Ext.DomHelper.useDom = true; // force it to use DOM; reduces performance
  150. *
  151. */
  152. (function() {
  153. // kill repeat to save bytes
  154. var afterbegin = 'afterbegin',
  155. afterend = 'afterend',
  156. beforebegin = 'beforebegin',
  157. beforeend = 'beforeend',
  158. ts = '&lt;table&gt;',
  159. te = '&lt;/table&gt;',
  160. tbs = ts+'&lt;tbody&gt;',
  161. tbe = '&lt;/tbody&gt;'+te,
  162. trs = tbs + '&lt;tr&gt;',
  163. tre = '&lt;/tr&gt;'+tbe,
  164. detachedDiv = document.createElement('div'),
  165. bbValues = ['BeforeBegin', 'previousSibling'],
  166. aeValues = ['AfterEnd', 'nextSibling'],
  167. bb_ae_PositionHash = {
  168. beforebegin: bbValues,
  169. afterend: aeValues
  170. },
  171. fullPositionHash = {
  172. beforebegin: bbValues,
  173. afterend: aeValues,
  174. afterbegin: ['AfterBegin', 'firstChild'],
  175. beforeend: ['BeforeEnd', 'lastChild']
  176. };
  177. <span id='Ext-dom-Helper'>/**
  178. </span> * The actual class of which {@link Ext.DomHelper} is instance of.
  179. *
  180. * Use singleton {@link Ext.DomHelper} instead.
  181. *
  182. * @private
  183. */
  184. Ext.define('Ext.dom.Helper', {
  185. extend: 'Ext.dom.AbstractHelper',
  186. tableRe: /^table|tbody|tr|td$/i,
  187. tableElRe: /td|tr|tbody/i,
  188. <span id='Ext-dom-Helper-property-useDom'> /**
  189. </span> * @property {Boolean} useDom
  190. * True to force the use of DOM instead of html fragments.
  191. */
  192. useDom : false,
  193. <span id='Ext-dom-Helper-method-createDom'> /**
  194. </span> * Creates new DOM element(s) without inserting them to the document.
  195. * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
  196. * @return {HTMLElement} The new uninserted node
  197. */
  198. createDom: function(o, parentNode){
  199. var el,
  200. doc = document,
  201. useSet,
  202. attr,
  203. val,
  204. cn,
  205. i, l;
  206. if (Ext.isArray(o)) { // Allow Arrays of siblings to be inserted
  207. el = doc.createDocumentFragment(); // in one shot using a DocumentFragment
  208. for (i = 0, l = o.length; i &lt; l; i++) {
  209. this.createDom(o[i], el);
  210. }
  211. } else if (typeof o == 'string') { // Allow a string as a child spec.
  212. el = doc.createTextNode(o);
  213. } else {
  214. el = doc.createElement(o.tag || 'div');
  215. useSet = !!el.setAttribute; // In IE some elements don't have setAttribute
  216. for (attr in o) {
  217. if (!this.confRe.test(attr)) {
  218. val = o[attr];
  219. if (attr == 'cls') {
  220. el.className = val;
  221. } else {
  222. if (useSet) {
  223. el.setAttribute(attr, val);
  224. } else {
  225. el[attr] = val;
  226. }
  227. }
  228. }
  229. }
  230. Ext.DomHelper.applyStyles(el, o.style);
  231. if ((cn = o.children || o.cn)) {
  232. this.createDom(cn, el);
  233. } else if (o.html) {
  234. el.innerHTML = o.html;
  235. }
  236. }
  237. if (parentNode) {
  238. parentNode.appendChild(el);
  239. }
  240. return el;
  241. },
  242. ieTable: function(depth, openingTags, htmlContent, closingTags){
  243. detachedDiv.innerHTML = [openingTags, htmlContent, closingTags].join('');
  244. var i = -1,
  245. el = detachedDiv,
  246. ns;
  247. while (++i &lt; depth) {
  248. el = el.firstChild;
  249. }
  250. // If the result is multiple siblings, then encapsulate them into one fragment.
  251. ns = el.nextSibling;
  252. if (ns) {
  253. el = document.createDocumentFragment();
  254. while (ns) {
  255. el.appendChild(ns);
  256. ns = ns.nextSibling;
  257. }
  258. }
  259. return el;
  260. },
  261. <span id='Ext-dom-Helper-method-insertIntoTable'> /**
  262. </span> * @private
  263. * Nasty code for IE's broken table implementation
  264. */
  265. insertIntoTable: function(tag, where, destinationEl, html) {
  266. var node,
  267. before,
  268. bb = where == beforebegin,
  269. ab = where == afterbegin,
  270. be = where == beforeend,
  271. ae = where == afterend;
  272. if (tag == 'td' &amp;&amp; (ab || be) || !this.tableElRe.test(tag) &amp;&amp; (bb || ae)) {
  273. return null;
  274. }
  275. before = bb ? destinationEl :
  276. ae ? destinationEl.nextSibling :
  277. ab ? destinationEl.firstChild : null;
  278. if (bb || ae) {
  279. destinationEl = destinationEl.parentNode;
  280. }
  281. if (tag == 'td' || (tag == 'tr' &amp;&amp; (be || ab))) {
  282. node = this.ieTable(4, trs, html, tre);
  283. } else if ((tag == 'tbody' &amp;&amp; (be || ab)) ||
  284. (tag == 'tr' &amp;&amp; (bb || ae))) {
  285. node = this.ieTable(3, tbs, html, tbe);
  286. } else {
  287. node = this.ieTable(2, ts, html, te);
  288. }
  289. destinationEl.insertBefore(node, before);
  290. return node;
  291. },
  292. <span id='Ext-dom-Helper-method-createContextualFragment'> /**
  293. </span> * @private
  294. * Fix for IE9 createContextualFragment missing method
  295. */
  296. createContextualFragment: function(html) {
  297. var fragment = document.createDocumentFragment(),
  298. length, childNodes;
  299. detachedDiv.innerHTML = html;
  300. childNodes = detachedDiv.childNodes;
  301. length = childNodes.length;
  302. // Move nodes into fragment, don't clone: http://jsperf.com/create-fragment
  303. while (length--) {
  304. fragment.appendChild(childNodes[0]);
  305. }
  306. return fragment;
  307. },
  308. applyStyles: function(el, styles) {
  309. if (styles) {
  310. el = Ext.fly(el);
  311. if (typeof styles == &quot;function&quot;) {
  312. styles = styles.call();
  313. }
  314. if (typeof styles == &quot;string&quot;) {
  315. styles = Ext.dom.Element.parseStyles(styles);
  316. }
  317. if (typeof styles == &quot;object&quot;) {
  318. el.setStyle(styles);
  319. }
  320. }
  321. },
  322. <span id='Ext-dom-Helper-method-createHtml'> /**
  323. </span> * Alias for {@link #markup}.
  324. * @inheritdoc Ext.dom.AbstractHelper#markup
  325. */
  326. createHtml: function(spec) {
  327. return this.markup(spec);
  328. },
  329. doInsert: function(el, o, returnElement, pos, sibling, append) {
  330. el = el.dom || Ext.getDom(el);
  331. var newNode;
  332. if (this.useDom) {
  333. newNode = this.createDom(o, null);
  334. if (append) {
  335. el.appendChild(newNode);
  336. }
  337. else {
  338. (sibling == 'firstChild' ? el : el.parentNode).insertBefore(newNode, el[sibling] || el);
  339. }
  340. } else {
  341. newNode = this.insertHtml(pos, el, this.markup(o));
  342. }
  343. return returnElement ? Ext.get(newNode, true) : newNode;
  344. },
  345. <span id='Ext-dom-Helper-method-overwrite'> /**
  346. </span> * Creates new DOM element(s) and overwrites the contents of el with them.
  347. * @param {String/HTMLElement/Ext.Element} el The context element
  348. * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
  349. * @param {Boolean} [returnElement] true to return an Ext.Element
  350. * @return {HTMLElement/Ext.Element} The new node
  351. */
  352. overwrite: function(el, html, returnElement) {
  353. var newNode;
  354. el = Ext.getDom(el);
  355. html = this.markup(html);
  356. // IE Inserting HTML into a table/tbody/tr requires extra processing: http://www.ericvasilik.com/2006/07/code-karma.html
  357. if (Ext.isIE &amp;&amp; this.tableRe.test(el.tagName)) {
  358. // Clearing table elements requires removal of all elements.
  359. while (el.firstChild) {
  360. el.removeChild(el.firstChild);
  361. }
  362. if (html) {
  363. newNode = this.insertHtml('afterbegin', el, html);
  364. return returnElement ? Ext.get(newNode) : newNode;
  365. }
  366. return null;
  367. }
  368. el.innerHTML = html;
  369. return returnElement ? Ext.get(el.firstChild) : el.firstChild;
  370. },
  371. insertHtml: function(where, el, html) {
  372. var hashVal,
  373. range,
  374. rangeEl,
  375. setStart,
  376. frag;
  377. where = where.toLowerCase();
  378. // Has fast HTML insertion into existing DOM: http://www.w3.org/TR/html5/apis-in-html-documents.html#insertadjacenthtml
  379. if (el.insertAdjacentHTML) {
  380. // IE's incomplete table implementation: http://www.ericvasilik.com/2006/07/code-karma.html
  381. if (Ext.isIE &amp;&amp; this.tableRe.test(el.tagName) &amp;&amp; (frag = this.insertIntoTable(el.tagName.toLowerCase(), where, el, html))) {
  382. return frag;
  383. }
  384. if ((hashVal = fullPositionHash[where])) {
  385. el.insertAdjacentHTML(hashVal[0], html);
  386. return el[hashVal[1]];
  387. }
  388. // if (not IE and context element is an HTMLElement) or TextNode
  389. } else {
  390. // we cannot insert anything inside a textnode so...
  391. if (el.nodeType === 3) {
  392. where = where === 'afterbegin' ? 'beforebegin' : where;
  393. where = where === 'beforeend' ? 'afterend' : where;
  394. }
  395. range = Ext.supports.CreateContextualFragment ? el.ownerDocument.createRange() : undefined;
  396. setStart = 'setStart' + (this.endRe.test(where) ? 'After' : 'Before');
  397. if (bb_ae_PositionHash[where]) {
  398. if (range) {
  399. range[setStart](el);
  400. frag = range.createContextualFragment(html);
  401. } else {
  402. frag = this.createContextualFragment(html);
  403. }
  404. el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);
  405. return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling'];
  406. } else {
  407. rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child';
  408. if (el.firstChild) {
  409. if (range) {
  410. range[setStart](el[rangeEl]);
  411. frag = range.createContextualFragment(html);
  412. } else {
  413. frag = this.createContextualFragment(html);
  414. }
  415. if (where == afterbegin) {
  416. el.insertBefore(frag, el.firstChild);
  417. } else {
  418. el.appendChild(frag);
  419. }
  420. } else {
  421. el.innerHTML = html;
  422. }
  423. return el[rangeEl];
  424. }
  425. }
  426. //&lt;debug&gt;
  427. Ext.Error.raise({
  428. sourceClass: 'Ext.DomHelper',
  429. sourceMethod: 'insertHtml',
  430. htmlToInsert: html,
  431. targetElement: el,
  432. msg: 'Illegal insertion point reached: &quot;' + where + '&quot;'
  433. });
  434. //&lt;/debug&gt;
  435. },
  436. <span id='Ext-dom-Helper-method-createTemplate'> /**
  437. </span> * Creates a new Ext.Template from the DOM object spec.
  438. * @param {Object} o The DOM object spec (and children)
  439. * @return {Ext.Template} The new template
  440. */
  441. createTemplate: function(o) {
  442. var html = this.markup(o);
  443. return new Ext.Template(html);
  444. }
  445. }, function() {
  446. Ext.ns('Ext.core');
  447. Ext.DomHelper = Ext.core.DomHelper = new this;
  448. });
  449. }());
  450. </pre>
  451. </body>
  452. </html>