No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 

309 líneas
8.9 KiB

  1. /*
  2. * Copyright (C) 2007-2018 Diego Perini
  3. * All rights reserved.
  4. *
  5. * CSS3 pseudo-classes extension for NWMatcher
  6. *
  7. * Added capabilities:
  8. *
  9. * - structural pseudo-classes
  10. *
  11. * :root, :empty,
  12. * :nth-child(), nth-of-type(),
  13. * :nth-last-child(), nth-last-of-type(),
  14. * :first-child, :last-child, :only-child
  15. * :first-of-type, :last-of-type, :only-of-type
  16. *
  17. * - negation, language, target and UI element pseudo-classes
  18. *
  19. * :not(), :target, :lang(), :target
  20. * :link, :visited, :active, :focus, :hover,
  21. * :checked, :disabled, :enabled, :selected
  22. */
  23. (function(global) {
  24. var LINK_NODES = {
  25. 'a': 1, 'A': 1,
  26. 'area': 1, 'AREA': 1,
  27. 'link': 1, 'LINK': 1
  28. },
  29. root = document.documentElement,
  30. contains = 'compareDocumentPosition' in root ?
  31. function(container, element) {
  32. return (container.compareDocumentPosition(element) & 16) == 16;
  33. } : 'contains' in root ?
  34. function(container, element) {
  35. return element.nodeType == 1 && container.contains(element);
  36. } :
  37. function(container, element) {
  38. while ((element = element.parentNode) && element.nodeType == 1) {
  39. if (element === container) return true;
  40. }
  41. return false;
  42. },
  43. isLink =
  44. function(element) {
  45. return element.getAttribute('href') && LINK_NODES[element.nodeName];
  46. },
  47. isEmpty =
  48. function(node) {
  49. node = node.firstChild;
  50. while (node) {
  51. if (node.nodeType == 3 || node.nodeName > '@') return false;
  52. node = node.nextSibling;
  53. }
  54. return true;
  55. },
  56. nthElement =
  57. function(element, last) {
  58. var count = 1, succ = last ? 'nextSibling' : 'previousSibling';
  59. while ((element = element[succ])) {
  60. if (element.nodeName > '@') ++count;
  61. }
  62. return count;
  63. },
  64. nthOfType =
  65. function(element, last) {
  66. var count = 1, succ = last ? 'nextSibling' : 'previousSibling', type = element.nodeName;
  67. while ((element = element[succ])) {
  68. if (element.nodeName == type) ++count;
  69. }
  70. return count;
  71. };
  72. NW.Dom.Snapshot['contains'] = contains;
  73. NW.Dom.Snapshot['isLink'] = isLink;
  74. NW.Dom.Snapshot['isEmpty'] = isEmpty;
  75. NW.Dom.Snapshot['nthOfType'] = nthOfType;
  76. NW.Dom.Snapshot['nthElement'] = nthElement;
  77. })(this);
  78. NW.Dom.registerSelector(
  79. 'nwmatcher:spseudos',
  80. /^\:(root|empty|(?:first|last|only)(?:-child|-of-type)|nth(?:-last)?(?:-child|-of-type)\(\s*(even|odd|(?:[-+]{0,1}\d*n\s*)?[-+]{0,1}\s*\d*)\s*\))?(.*)/i,
  81. (function(global) {
  82. return function(match, source) {
  83. var a, n, b, status = true, test, type;
  84. switch (match[1]) {
  85. case 'root':
  86. if (match[3])
  87. source = 'if(e===h||s.contains(h,e)){' + source + '}';
  88. else
  89. source = 'if(e===h){' + source + '}';
  90. break;
  91. case 'empty':
  92. source = 'if(s.isEmpty(e)){' + source + '}';
  93. break;
  94. default:
  95. if (match[1] && match[2]) {
  96. if (match[2] == 'n') {
  97. source = 'if(e!==h){' + source + '}';
  98. break;
  99. } else if (match[2] == 'even') {
  100. a = 2;
  101. b = 0;
  102. } else if (match[2] == 'odd') {
  103. a = 2;
  104. b = 1;
  105. } else {
  106. b = ((n = match[2].match(/(-?\d+)$/)) ? parseInt(n[1], 10) : 0);
  107. a = ((n = match[2].match(/(-?\d*)n/i)) ? parseInt(n[1], 10) : 0);
  108. if (n && n[1] == '-') a = -1;
  109. }
  110. test = a > 1 ?
  111. (/last/i.test(match[1])) ? '(n-(' + b + '))%' + a + '==0' :
  112. 'n>=' + b + '&&(n-(' + b + '))%' + a + '==0' : a < -1 ?
  113. (/last/i.test(match[1])) ? '(n-(' + b + '))%' + a + '==0' :
  114. 'n<=' + b + '&&(n-(' + b + '))%' + a + '==0' : a === 0 ?
  115. 'n==' + b : a == -1 ? 'n<=' + b : 'n>=' + b;
  116. source =
  117. 'if(e!==h){' +
  118. 'n=s[' + (/-of-type/i.test(match[1]) ? '"nthOfType"' : '"nthElement"') + ']' +
  119. '(e,' + (/last/i.test(match[1]) ? 'true' : 'false') + ');' +
  120. 'if(' + test + '){' + source + '}' +
  121. '}';
  122. } else if (match[1]) {
  123. a = /first/i.test(match[1]) ? 'previous' : 'next';
  124. n = /only/i.test(match[1]) ? 'previous' : 'next';
  125. b = /first|last/i.test(match[1]);
  126. type = /-of-type/i.test(match[1]) ? '&&n.nodeName!==e.nodeName' : '&&n.nodeName<"@"';
  127. source = 'if(e!==h){' +
  128. ( 'n=e;while((n=n.' + a + 'Sibling)' + type + ');if(!n){' + (b ? source :
  129. 'n=e;while((n=n.' + n + 'Sibling)' + type + ');if(!n){' + source + '}') + '}' ) + '}';
  130. } else {
  131. status = false;
  132. }
  133. break;
  134. }
  135. return {
  136. 'source': source,
  137. 'status': status
  138. };
  139. };
  140. })(this));
  141. NW.Dom.registerSelector(
  142. 'nwmatcher:dpseudos',
  143. /^\:(link|visited|target|active|focus|hover|checked|disabled|enabled|selected|lang\(([-\w]{2,})\)|not\(\s*(:nth(?:-last)?(?:-child|-of-type)\(\s*(?:even|odd|(?:[-+]{0,1}\d*n\s*)?[-+]{0,1}\s*\d*)\s*\)|[^()]*)\s*\))?(.*)/i,
  144. (function(global) {
  145. var doc = global.document,
  146. Config = NW.Dom.Config,
  147. Tokens = NW.Dom.Tokens,
  148. reTrimSpace = RegExp('^\\s+|\\s+$', 'g'),
  149. reSimpleNot = RegExp('^((?!:not)' +
  150. '(' + Tokens.prefixes + '|' + Tokens.identifier +
  151. '|\\([^()]*\\))+|\\[' + Tokens.attributes + '\\])$');
  152. return function(match, source) {
  153. var expr, status = true, test;
  154. switch (match[1].match(/^\w+/)[0]) {
  155. case 'not':
  156. expr = match[3].replace(reTrimSpace, '');
  157. if (Config.SIMPLENOT && !reSimpleNot.test(expr)) {
  158. NW.Dom.emit('Negation pseudo-class only accepts simple selectors "' + selector + '"');
  159. } else {
  160. if ('compatMode' in doc) {
  161. source = 'if(!' + NW.Dom.compile(expr, '', false) + '(e,s,d,h,g)){' + source + '}';
  162. } else {
  163. source = 'if(!s.match(e, "' + expr.replace(/\x22/g, '\\"') + '",g)){' + source +'}';
  164. }
  165. }
  166. break;
  167. case 'checked':
  168. source = 'if((typeof e.form!=="undefined"&&(/^(?:radio|checkbox)$/i).test(e.type)&&e.checked)' +
  169. (Config.USE_HTML5 ? '||(/^option$/i.test(e.nodeName)&&(e.selected||e.checked))' : '') +
  170. '){' + source + '}';
  171. break;
  172. case 'disabled':
  173. source = 'if(((typeof e.form!=="undefined"' +
  174. (Config.USE_HTML5 ? '' : '&&!(/^hidden$/i).test(e.type)') +
  175. ')||s.isLink(e))&&e.disabled===true){' + source + '}';
  176. break;
  177. case 'enabled':
  178. source = 'if(((typeof e.form!=="undefined"' +
  179. (Config.USE_HTML5 ? '' : '&&!(/^hidden$/i).test(e.type)') +
  180. ')||s.isLink(e))&&e.disabled===false){' + source + '}';
  181. break;
  182. case 'lang':
  183. test = '';
  184. if (match[2]) test = match[2].substr(0, 2) + '-';
  185. source = 'do{(n=e.lang||"").toLowerCase();' +
  186. 'if((n==""&&h.lang=="' + match[2].toLowerCase() + '")||' +
  187. '(n&&(n=="' + match[2].toLowerCase() +
  188. '"||n.substr(0,3)=="' + test.toLowerCase() + '")))' +
  189. '{' + source + 'break;}}while((e=e.parentNode)&&e!==g);';
  190. break;
  191. case 'target':
  192. source = 'if(e.id==d.location.hash.slice(1)){' + source + '}';
  193. break;
  194. case 'link':
  195. source = 'if(s.isLink(e)&&!e.visited){' + source + '}';
  196. break;
  197. case 'visited':
  198. source = 'if(s.isLink(e)&&e.visited){' + source + '}';
  199. break;
  200. case 'active':
  201. source = 'if(e===d.activeElement){' + source + '}';
  202. break;
  203. case 'hover':
  204. source = 'if(e===d.hoverElement){' + source + '}';
  205. break;
  206. case 'focus':
  207. source = 'hasFocus' in doc ?
  208. 'if(e===d.activeElement&&d.hasFocus()&&(e.type||e.href||typeof e.tabIndex=="number")){' + source + '}' :
  209. 'if(e===d.activeElement&&(e.type||e.href)){' + source + '}';
  210. break;
  211. case 'selected':
  212. source = 'if(/^option$/i.test(e.nodeName)&&(e.selected||e.checked)){' + source + '}';
  213. break;
  214. default:
  215. status = false;
  216. break;
  217. }
  218. return {
  219. 'source': source,
  220. 'status': status
  221. };
  222. };
  223. })(this));
  224. NW.Dom.registerSelector(
  225. 'nwmatcher:epseudos',
  226. /^((?:[:]{1,2}(?:after|before|first-letter|first-line))|(?:[:]{2,2}(?:selection|backdrop|placeholder)))?(.*)/i,
  227. (function(global) {
  228. return function(match, source) {
  229. var status = true;
  230. switch (match[1].match(/(\w+)$/)[0]) {
  231. case 'after':
  232. case 'before':
  233. case 'first-letter':
  234. case 'first-line':
  235. case 'selection':
  236. case 'backdrop':
  237. case 'placeholder':
  238. source = 'if(!(/1|11/).test(e.nodeType)){' + source + '}';
  239. break;
  240. default:
  241. status = false;
  242. break;
  243. }
  244. return {
  245. 'source': source,
  246. 'status': status
  247. };
  248. };
  249. })(this));