XTemplateParser.html 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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-XTemplateParser'>/**
  19. </span> * This class parses the XTemplate syntax and calls abstract methods to process the parts.
  20. * @private
  21. */
  22. Ext.define('Ext.XTemplateParser', {
  23. constructor: function (config) {
  24. Ext.apply(this, config);
  25. },
  26. <span id='Ext-XTemplateParser-property-level'> /**
  27. </span> * @property {Number} level The 'for' loop context level. This is adjusted up by one
  28. * prior to calling {@link #doFor} and down by one after calling the corresponding
  29. * {@link #doEnd} that closes the loop. This will be 1 on the first {@link #doFor}
  30. * call.
  31. */
  32. <span id='Ext-XTemplateParser-method-doText'> /**
  33. </span> * This method is called to process a piece of raw text from the tpl.
  34. * @param {String} text
  35. * @method doText
  36. */
  37. // doText: function (text)
  38. <span id='Ext-XTemplateParser-method-doExpr'> /**
  39. </span> * This method is called to process expressions (like `{[expr]}`).
  40. * @param {String} expr The body of the expression (inside &quot;{[&quot; and &quot;]}&quot;).
  41. * @method doExpr
  42. */
  43. // doExpr: function (expr)
  44. <span id='Ext-XTemplateParser-method-doTag'> /**
  45. </span> * This method is called to process simple tags (like `{tag}`).
  46. * @method doTag
  47. */
  48. // doTag: function (tag)
  49. <span id='Ext-XTemplateParser-method-doElse'> /**
  50. </span> * This method is called to process `&lt;tpl else&gt;`.
  51. * @method doElse
  52. */
  53. // doElse: function ()
  54. <span id='Ext-XTemplateParser-method-doEval'> /**
  55. </span> * This method is called to process `{% text %}`.
  56. * @param {String} text
  57. * @method doEval
  58. */
  59. // doEval: function (text)
  60. <span id='Ext-XTemplateParser-method-doIf'> /**
  61. </span> * This method is called to process `&lt;tpl if=&quot;action&quot;&gt;`. If there are other attributes,
  62. * these are passed in the actions object.
  63. * @param {String} action
  64. * @param {Object} actions Other actions keyed by the attribute name (such as 'exec').
  65. * @method doIf
  66. */
  67. // doIf: function (action, actions)
  68. <span id='Ext-XTemplateParser-method-doElseIf'> /**
  69. </span> * This method is called to process `&lt;tpl elseif=&quot;action&quot;&gt;`. If there are other attributes,
  70. * these are passed in the actions object.
  71. * @param {String} action
  72. * @param {Object} actions Other actions keyed by the attribute name (such as 'exec').
  73. * @method doElseIf
  74. */
  75. // doElseIf: function (action, actions)
  76. <span id='Ext-XTemplateParser-method-doSwitch'> /**
  77. </span> * This method is called to process `&lt;tpl switch=&quot;action&quot;&gt;`. If there are other attributes,
  78. * these are passed in the actions object.
  79. * @param {String} action
  80. * @param {Object} actions Other actions keyed by the attribute name (such as 'exec').
  81. * @method doSwitch
  82. */
  83. // doSwitch: function (action, actions)
  84. <span id='Ext-XTemplateParser-method-doCase'> /**
  85. </span> * This method is called to process `&lt;tpl case=&quot;action&quot;&gt;`. If there are other attributes,
  86. * these are passed in the actions object.
  87. * @param {String} action
  88. * @param {Object} actions Other actions keyed by the attribute name (such as 'exec').
  89. * @method doCase
  90. */
  91. // doCase: function (action, actions)
  92. <span id='Ext-XTemplateParser-method-doDefault'> /**
  93. </span> * This method is called to process `&lt;tpl default&gt;`.
  94. * @method doDefault
  95. */
  96. // doDefault: function ()
  97. <span id='Ext-XTemplateParser-method-doEnd'> /**
  98. </span> * This method is called to process `&lt;/tpl&gt;`. It is given the action type that started
  99. * the tpl and the set of additional actions.
  100. * @param {String} type The type of action that is being ended.
  101. * @param {Object} actions The other actions keyed by the attribute name (such as 'exec').
  102. * @method doEnd
  103. */
  104. // doEnd: function (type, actions)
  105. <span id='Ext-XTemplateParser-method-doFor'> /**
  106. </span> * This method is called to process `&lt;tpl for=&quot;action&quot;&gt;`. If there are other attributes,
  107. * these are passed in the actions object.
  108. * @param {String} action
  109. * @param {Object} actions Other actions keyed by the attribute name (such as 'exec').
  110. * @method doFor
  111. */
  112. // doFor: function (action, actions)
  113. <span id='Ext-XTemplateParser-method-doExec'> /**
  114. </span> * This method is called to process `&lt;tpl exec=&quot;action&quot;&gt;`. If there are other attributes,
  115. * these are passed in the actions object.
  116. * @param {String} action
  117. * @param {Object} actions Other actions keyed by the attribute name.
  118. * @method doExec
  119. */
  120. // doExec: function (action, actions)
  121. <span id='Ext-XTemplateParser-method-doTpl'> /**
  122. </span> * This method is called to process an empty `&lt;tpl&gt;`. This is unlikely to need to be
  123. * implemented, so a default (do nothing) version is provided.
  124. * @method
  125. */
  126. doTpl: Ext.emptyFn,
  127. parse: function (str) {
  128. var me = this,
  129. len = str.length,
  130. aliases = { elseif: 'elif' },
  131. topRe = me.topRe,
  132. actionsRe = me.actionsRe,
  133. index, stack, s, m, t, prev, frame, subMatch, begin, end, actions,
  134. prop;
  135. me.level = 0;
  136. me.stack = stack = [];
  137. for (index = 0; index &lt; len; index = end) {
  138. topRe.lastIndex = index;
  139. m = topRe.exec(str);
  140. if (!m) {
  141. me.doText(str.substring(index, len));
  142. break;
  143. }
  144. begin = m.index;
  145. end = topRe.lastIndex;
  146. if (index &lt; begin) {
  147. me.doText(str.substring(index, begin));
  148. }
  149. if (m[1]) {
  150. end = str.indexOf('%}', begin+2);
  151. me.doEval(str.substring(begin+2, end));
  152. end += 2;
  153. } else if (m[2]) {
  154. end = str.indexOf(']}', begin+2);
  155. me.doExpr(str.substring(begin+2, end));
  156. end += 2;
  157. } else if (m[3]) { // if ('{' token)
  158. me.doTag(m[3]);
  159. } else if (m[4]) { // content of a &lt;tpl xxxxxx xxx&gt; tag
  160. actions = null;
  161. while ((subMatch = actionsRe.exec(m[4])) !== null) {
  162. s = subMatch[2] || subMatch[3];
  163. if (s) {
  164. s = Ext.String.htmlDecode(s); // decode attr value
  165. t = subMatch[1];
  166. t = aliases[t] || t;
  167. actions = actions || {};
  168. prev = actions[t];
  169. if (typeof prev == 'string') {
  170. actions[t] = [prev, s];
  171. } else if (prev) {
  172. actions[t].push(s);
  173. } else {
  174. actions[t] = s;
  175. }
  176. }
  177. }
  178. if (!actions) {
  179. if (me.elseRe.test(m[4])) {
  180. me.doElse();
  181. } else if (me.defaultRe.test(m[4])) {
  182. me.doDefault();
  183. } else {
  184. me.doTpl();
  185. stack.push({ type: 'tpl' });
  186. }
  187. }
  188. else if (actions['if']) {
  189. me.doIf(actions['if'], actions);
  190. stack.push({ type: 'if' });
  191. }
  192. else if (actions['switch']) {
  193. me.doSwitch(actions['switch'], actions);
  194. stack.push({ type: 'switch' });
  195. }
  196. else if (actions['case']) {
  197. me.doCase(actions['case'], actions);
  198. }
  199. else if (actions['elif']) {
  200. me.doElseIf(actions['elif'], actions);
  201. }
  202. else if (actions['for']) {
  203. ++me.level;
  204. // Extract property name to use from indexed item
  205. if (prop = me.propRe.exec(m[4])) {
  206. actions.propName = prop[1] || prop[2];
  207. }
  208. me.doFor(actions['for'], actions);
  209. stack.push({ type: 'for', actions: actions });
  210. }
  211. else if (actions.exec) {
  212. me.doExec(actions.exec, actions);
  213. stack.push({ type: 'exec', actions: actions });
  214. }
  215. /*
  216. else {
  217. // todo - error
  218. }
  219. */
  220. } else if (m[0].length === 5) {
  221. // if the length of m[0] is 5, assume that we're dealing with an opening tpl tag with no attributes (e.g. &lt;tpl&gt;...&lt;/tpl&gt;)
  222. // in this case no action is needed other than pushing it on to the stack
  223. stack.push({ type: 'tpl' });
  224. } else {
  225. frame = stack.pop();
  226. me.doEnd(frame.type, frame.actions);
  227. if (frame.type == 'for') {
  228. --me.level;
  229. }
  230. }
  231. }
  232. },
  233. // Internal regexes
  234. topRe: /(?:(\{\%)|(\{\[)|\{([^{}]*)\})|(?:&lt;tpl([^&gt;]*)\&gt;)|(?:&lt;\/tpl&gt;)/g,
  235. actionsRe: /\s*(elif|elseif|if|for|exec|switch|case|eval)\s*\=\s*(?:(?:&quot;([^&quot;]*)&quot;)|(?:'([^']*)'))\s*/g,
  236. propRe: /prop=(?:(?:&quot;([^&quot;]*)&quot;)|(?:'([^']*)'))/,
  237. defaultRe: /^\s*default\s*$/,
  238. elseRe: /^\s*else\s*$/
  239. });
  240. </pre>
  241. </body>
  242. </html>