nwsapi-jquery.js 4.18 KB
Newer Older
YazhouChen's avatar
YazhouChen committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
/*
 * Copyright (C) 2007-2017 Diego Perini
 * All rights reserved.
 *
 * this is just a small example to show
 * how an extension for NWMatcher could be
 * adapted to handle special jQuery selectors
 *
 * Child Selectors
 * :even, :odd, :eq, :lt, :gt, :first, :last, :nth
 *
 * Pseudo Selectors
 * :has, :button, :header, :input, :checkbox, :radio, :file, :image
 * :password, :reset, :submit, :text, :hidden, :visible, :parent
 *
 */

// for structural pseudo-classes extensions
NW.Dom.registerSelector(
  'jquery:child',
  /^\:((?:(nth|eq|lt|gt)\(([^()]*)\))|(?:even|odd|first|last))(.*)/i,
  (function(global) {

    return function(match, source, mode, callback) {

      var status = true,
      macro = mode ? NW.Dom.S_BODY : NW.Dom.M_BODY;

      macro = macro.replace('@', typeof callback == 'function' ? (mode ? NW.Dom.S_TEST : NW.Dom.M_TEST) : '');

      switch (match[1].toLowerCase()) {
        case 'odd':
          source = source.replace(macro, 'if((n=n^1)==0){' + macro + '}');
          break;
        case 'even':
          source = source.replace(macro, 'if((n=n^1)==1){' + macro + '}');
          break;
        case 'first':
          source = 'n=s.root.getElementsByTagName(e.nodeName);if(n.length&&n[0]===e){' + source + '}';
          break;
        case 'last':
          source = 'n=s.root.getElementsByTagName(e.nodeName);if(n.length&&n[n.length-1]===e){' + source + '}';
          break;
        default:
          switch (match[2].toLowerCase()) {
            case 'nth':
              source = 'n=s.root.getElementsByTagName(e.nodeName);if(n.length&&n[' + match[3] + ']===e){' + source + '}';
              break;
            case 'eq':
              source = source.replace(macro, 'if(x++==' + match[3] + '){' + macro + '}');
              break;
            case 'lt':
              source = source.replace(macro, 'if(x++<' + match[3] + '){' + macro + '}');
              break;
            case 'gt':
              source = source.replace(macro, 'if(x++>' + match[3] + '){' + macro + '}');
              break;
            default:
              status = false;
              break;
          }
          break;
      }

      // compiler will add this to "source"
      return {
        'source': source,
        'status': status,
        'modvar': 'x=0'
      };

    };

  })(this));

// for element pseudo-classes extensions
NW.Dom.registerSelector(
  'jquery:pseudo',
  /^\:(has|checkbox|file|image|password|radio|reset|submit|text|button|input|header|hidden|visible|parent)(?:\(\s*(["']*)?([^'"()]*)\2\s*\))?(.*)/i,
  (function(global) {

    return function(match, source, mode, callback) {

      var status = true,
      macro = mode ? NW.Dom.S_BODY : NW.Dom.M_BODY;

      macro = macro.replace('@', typeof callback == 'function' ? (mode ? NW.Dom.S_TEST : NW.Dom.M_TEST) : '');

      switch(match[1].toLowerCase()) {
        case 'has':
          source = source.replace(macro, 'if(e.getElementsByTagName("' + match[3].replace(/^\s|\s$/g, '') + '")[0]){' + macro + '}');
          break;
        case 'checkbox':
        case 'file':
        case 'image':
        case 'password':
        case 'radio':
        case 'reset':
        case 'submit':
        case 'text':
          // :checkbox, :file, :image, :password, :radio, :reset, :submit, :text
          source = 'if(/^' + match[1] + '$/i.test(e.type)){' + source + '}';
          break;
        case 'button':
          source = 'if(/^button$/i.test(e.nodeName)){' + source + '}';
          break;
        case 'input':
          source = 'if(/^(?:button|input|select|textarea)$/i.test(e.nodeName)){' + source + '}';
          break;
        case 'header':
          source = 'if(/^h[1-6]$/i.test(e.nodeName)){' + source + '}';
          break;
        case 'hidden':
          source = 'if(!e.offsetWidth&&!e.offsetHeight){' + source + '}';
          break;
        case 'visible':
          source = 'if(e.offsetWidth||e.offsetHeight){' + source + '}';
          break;
        case 'parent':
          source = 'if(e.firstChild){' + source + '}';
          break;
        default:
          status = false;
          break;
      }

      // compiler will add this to "source"
      return {
        'source': source,
        'status': status
      };

    };

  })(this));