├── .github └── FUNDING.yml ├── .gitignore ├── Images └── Logo.fla ├── LICENSE ├── README.md ├── dist ├── selector.js └── selector.min.js ├── gulpfile.js ├── index.html ├── package.json ├── selector.js └── tests ├── 01-simple ├── index.html ├── style.css ├── test.js └── velocity.js ├── 02-over-9000 ├── debug.log ├── iframe_jquery.html ├── iframe_selector.html ├── iframe_zepto.html ├── index.html ├── jquery-3.2.0.min.js ├── runtest.js ├── style.css ├── test.js └── zepto-1.2.0.min.js └── style.css /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [datasilk] -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | package-lock.json -------------------------------------------------------------------------------- /Images/Logo.fla: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Datasilk/Selector/e2ea6917b29e296b2a6ed7f4368d435e958a35e2/Images/Logo.fla -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Websilk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Selector 2 | A micro JavaScript library used as a replacement for jQuery, weighing in at nearly 5KB. 3 | 4 | The aim of this project is to build a library that can be used to replace jQuery. The challenge will be to shrink the overall filesize of the library, keeping the minified, gzip compressed file under 5KB while simultaniously adding more support for jQuery features. The ultimate goal is to have a modern library that runs faster than jQuery under stress. 5 | 6 | [View Demo](https://jsfiddle.net/markentingh/L2o0qrwy/) 7 | 8 | ### Add to your project via public CDN from jsDelivr 9 | [https://cdn.jsdelivr.net/selectorjs/0.9.12/selector.min.js](https://cdn.jsdelivr.net/selectorjs/0.9.12/selector.min.js) 10 | 11 | ### File size comparison between jQuery and selector.js 12 | 13 | | Library | **Selector.js**| jQuery 3.2 | jQuery 3.2 Slim | 14 | | ------------------------- | --------------:| -----------:| ----------------:| 15 | | Uncompressed | **68K** | 271K | 217K | 16 | | Minified | **16K** | 84.5K | 68K | 17 | | **Minified & Gzipped** | **4.8K** | 28.6K | 22.7K | 18 | 19 | ### Supported jQuery selector functions 20 | * add 21 | * addClass 22 | * after 23 | * animate (requires Velocity.js) 24 | * append 25 | * attr 26 | * before 27 | * children 28 | * closest 29 | * css 30 | * each 31 | * empty 32 | * eq 33 | * filter 34 | * find 35 | * first 36 | * get 37 | * has 38 | * hasClass 39 | * height 40 | * hide 41 | * hover 42 | * html 43 | * index 44 | * innerHeight 45 | * innerWidth 46 | * is 47 | * last 48 | * map 49 | * next 50 | * nextAll 51 | * not 52 | * off 53 | * offset 54 | * offsetParent 55 | * on 56 | * parent 57 | * parents 58 | * position 59 | * prepend 60 | * prev 61 | * prop 62 | * push (*pushStack) 63 | * ready 64 | * remove 65 | * removeAttr 66 | * removeClass 67 | * removeProp 68 | * serialize 69 | * show 70 | * siblings 71 | * slice 72 | * stop (requires Velocity.js) 73 | * toggle 74 | * toggleClass 75 | * val 76 | * width 77 | 78 | ### Supported jQuery objects 79 | * $ 80 | 81 | ### Supported jQuery functions 82 | * $.ajax 83 | * $.extend 84 | 85 | ### Unsupported jQuery functionality 86 | * jQuery object 87 | * All jQuery plugins 88 | * jQuery UI 89 | * jQuery.fx 90 | * Deprecated functions 91 | * More... 92 | 93 | 94 | ## Disclaimer 95 | This project is in beta and has been tested in Chrome 51+, IE8+ (using ie-shim.js), Safari 9+, and iOS 6+. Use at your own risk. 96 | 97 | #### NOTES 98 | * *pushStack is now called push -------------------------------------------------------------------------------- /dist/selector.js: -------------------------------------------------------------------------------- 1 | // selector.js - micro library as a jQuery replacement 2 | // https://github.com/Websilk/Selector 3 | // copyright 2017 by Mark Entingh 4 | 5 | (function () { 6 | 7 | //global variables 8 | const tru = true; 9 | const fals = false; 10 | const doc = document; 11 | const pxStyles = ['top', 'right', 'bottom', 'left', 'width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight', 'fontSize'], 12 | pxStylesPrefix = ['border', 'padding', 'margin'], 13 | listeners = []; //used for capturing event listeners from $('').on 14 | //listeners = [{ elem: null, events: [{ name: '', list: [[selector, event]] }] }]; 15 | 16 | const classMatch = /^\.[\w-]*$/, 17 | singlet = /^\w+$/; 18 | 19 | let ajaxQueue = []; 20 | let ajaxWait = false; 21 | 22 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 23 | //Internal functions ////////////////////////////////////////////////////////////////////////////////////////////// 24 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 25 | 26 | /** 27 | * selector 28 | * @constructor 29 | */ 30 | function select(sel) { 31 | //main function, instantiated via $(sel) 32 | if (sel) { this.push(query(document, sel)); } 33 | return this; 34 | } 35 | 36 | function query(context, selector) { 37 | //gets a list of elements from a CSS selector 38 | if (context == null) { return [];} 39 | let elems = []; 40 | if (isType(selector,4)) { 41 | //elements are already defined instead of using a selector ///////////////////////////////////// 42 | elems = isType(selector, 5) ? selector : [selector]; 43 | } else if (selector != null && selector != '') { 44 | //only use vanilla Javascript to select DOM elements based on a CSS selector (Chrome 1, IE 9, Safari 3.2, Firefox 3.5, Opera 10) 45 | context = context || doc; 46 | const el = ( 47 | classMatch.test(selector) ? 48 | context.getElementsByClassName(selector.slice(1)) : 49 | singlet.test(selector) ? 50 | context.getElementsByTagName(selector) : 51 | context.querySelectorAll(selector) 52 | ); 53 | //convert node list into array 54 | for (let i = el.length; i--; elems.unshift(el[i])) { }; 55 | } 56 | return elems; 57 | } 58 | 59 | function isDescendant(parent, child) { 60 | //checks if element is child of another element 61 | let node = child; 62 | while (node != null) { 63 | node = node.parentNode; 64 | if (node == parent) { 65 | return tru; 66 | } 67 | } 68 | return fals; 69 | } 70 | 71 | function styleName(str) { 72 | //gets the proper style name from shorthand string 73 | //for example: border-width translates to borderWidth; 74 | if (str.indexOf('-') < 0) { return str; } 75 | const name = str.split('-'); 76 | if(name.length > 1){name[1] = name[1][0].toUpperCase() + name[1].substr(1);} 77 | return name.join(''); 78 | } 79 | 80 | function setStyle(e, n, val) { 81 | //properly set a style for an element 82 | if (e.nodeName == '#text') { return; } 83 | let v = val; 84 | 85 | //check for empty value 86 | 87 | if (v === '' || v === null) { 88 | e.style[n] = v == '' ? null : v; return; 89 | } 90 | 91 | //check for numbers that should be using 'px'; 92 | 93 | if ((Number(v) == v || v === 0) && v.toString().indexOf('%') < 0) { 94 | if (pxStyles.indexOf(n) >= 0) { 95 | v = val + 'px'; 96 | } else if (pxStylesPrefix.some(function (a) { return n.indexOf(a) == 0 }) === true) { 97 | v = val + 'px'; 98 | } 99 | } 100 | 101 | //last resort, set style to string value\ 102 | e.style[n] = v; 103 | } 104 | 105 | function getObj(obj) { 106 | //get a string from object (either string, number, or function) 107 | if (obj == null) { return null; } 108 | if (isType(obj, 1)) { 109 | //handle object as string 110 | return obj; 111 | } 112 | if (isType(obj, 5)) { 113 | //handle object as array 114 | return obj[0]; 115 | } 116 | if (isType(obj, 6)) { 117 | //handle object as function (get value from object function execution) 118 | return getObj(obj()); 119 | } 120 | return obj; 121 | } 122 | 123 | function diffArray(arr, remove) { 124 | return arr.filter(function (el) { 125 | return !remove.includes(el); 126 | }); 127 | } 128 | 129 | function isArrayThen(obj, arrayFunc) { 130 | if (isType(obj, 5)) { 131 | //handle content as array 132 | for(let x in obj){ 133 | arrayFunc.call(this,obj[x]); 134 | } 135 | return tru; 136 | } 137 | return fals; 138 | } 139 | 140 | function isType(obj, type) { 141 | if(obj != null){ 142 | switch (type) { 143 | case 0: return tru; //anything 144 | case 1: return typeof (obj) == 'string'; //string 145 | case 2: return typeof (obj) == 'boolean'; //boolean 146 | case 3: return !isNaN(parseFloat(obj)) && isFinite(obj); //number 147 | case 4: return typeof (obj) == 'object'; //object 148 | case 5: return typeof obj.splice === 'function'; //array 149 | case 6: return typeof obj == 'function'; //function 150 | } 151 | } 152 | return fals; 153 | } 154 | 155 | function normalizeArgs(types, args) { 156 | let results = [], 157 | a = [].slice.call(args), //convert arguments object into array 158 | step = types.length - 1, 159 | req, skip; 160 | for (let x = a.length-1; x >= 0; x--) { 161 | for (let i = step; i >= 0; i--) { 162 | skip = fals; 163 | if (types[i].o == tru) { 164 | //make sure there are enough arguments 165 | //left over for required types 166 | req = 0; 167 | for (let t = 0; t <= i; t++) { 168 | if (types[t].o == fals) { req++;} 169 | } 170 | skip = req > x; 171 | } 172 | if (skip == fals) { skip = !isType(a[x], types[i].t) && a[x] != null; } 173 | 174 | results[i] = !skip ? a[x] : null; 175 | step = i - 1; 176 | if (!skip || a[x] == null) { break; } 177 | } 178 | } 179 | return results; 180 | } 181 | 182 | function insertContent(obj, elements, stringFunc, objFunc) { 183 | //checks type of object and execute callback functions depending on object type 184 | const type = isType(obj, 1); 185 | if (type == tru) { 186 | for (let x = 0; x < elements.length; x++) { 187 | stringFunc(elements[x]); 188 | } 189 | } else { 190 | for (let x = 0; x < elements.length; x++) { 191 | objFunc(elements[x]); 192 | } 193 | } 194 | 195 | return this; 196 | } 197 | 198 | function clone(elems) { 199 | let n = new select(null); 200 | return n.push(elems); 201 | } 202 | 203 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 204 | //prototype functions that are accessable by $(selector) ////////////////////////////////////////////////////////// 205 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 206 | select.prototype = { 207 | 208 | add: function (elems) { 209 | //Add new (unique) elements to the existing elements array 210 | let obj = getObj(elems); 211 | if (!obj) { return this; } 212 | if (obj.elements) { obj = obj.elements; } 213 | for (let x in obj) { 214 | //check for duplicates 215 | if (this.indexOf(obj[x]) < 0) { 216 | //element is unique 217 | this.push(obj[x]); 218 | } 219 | } 220 | return this; 221 | }, 222 | 223 | addClass: function (classes) { 224 | //Add class name to each of the elements in the collection. 225 | //Multiple class names can be given in a space-separated string. 226 | if (this.length > 0) { 227 | const classList = classes.split(' '); 228 | for (let x = 0; x < this.length; x++) { 229 | let e = this[x]; 230 | //alter classname for each element in selector 231 | if (e.className) { 232 | let className = e.className; 233 | const list = className.split(' '); 234 | for (let c in classList) { 235 | if (list.indexOf(classList[c]) < 0) { 236 | //class doesn't exist in element classname list 237 | className += ' ' + classList[c]; 238 | } 239 | } 240 | //finally, change element classname if it was altered 241 | e.className = className; 242 | } else { 243 | e.className = classes; 244 | } 245 | } 246 | } 247 | return this; 248 | }, 249 | 250 | after: function (content) { 251 | //Add content to the DOM after each elements in the collection. 252 | //The content can be an HTML string, a DOM node or an array of nodes. 253 | let obj = getObj(content); 254 | if (isArrayThen(obj, this.after) || obj == null) { return this; } 255 | 256 | insertContent(obj, this, 257 | function (e) { e.insertAdjacentHTML('afterend', obj); }, 258 | function (e) { e.parentNode.insertBefore(obj, e.nextSibling); } 259 | ); 260 | return this; 261 | }, 262 | 263 | animate: function (props, options) { 264 | if (typeof (Velocity) != 'undefined') { 265 | Velocity(this, props, options); 266 | } 267 | return this; 268 | }, 269 | 270 | append: function (content) { 271 | //Append content to the DOM inside each individual element in the collection. 272 | //The content can be an HTML string, a DOM node or an array of nodes. 273 | 274 | let obj = getObj(content); 275 | if (isArrayThen.call(this, obj, this.append) || obj == null) { return this; } 276 | insertContent(obj, this, 277 | function (e) { e.insertAdjacentHTML('beforeend', obj); }, 278 | function (e) { e.appendChild(obj); } 279 | ); 280 | return this; 281 | }, 282 | 283 | attr: function (name, val) { 284 | //Read or set DOM attributes. When no value is given, reads 285 | //specified attribute from the first element in the collection. 286 | //When value is given, sets the attribute to that value on each element 287 | //in the collection. When value is null, the attribute is removed = function(like with removeAttr). 288 | //Multiple attributes can be set by passing an object with name-value pairs. 289 | let n = getObj(name), v = getObj(val); 290 | if (isType(n, 5)) { 291 | //get array of attribute values from first element 292 | let attrs = {}; 293 | for (let p in n) { 294 | attrs[n[p]] = this.length > 0 ? this[0].getAttribute(n[p]) : attrs[n[p]] = ''; 295 | } 296 | return attrs; 297 | } else { 298 | if (v != null) { 299 | //set single attribute value to all elements in list 300 | for (let x = 0; x < this.length; x++) { 301 | this[x].setAttribute(n, v); 302 | } 303 | } else { 304 | //get single attribute value from first element in list 305 | return this.length > 0 ? this[0].getAttribute(n) : ''; 306 | } 307 | } 308 | return this; 309 | }, 310 | 311 | before: function (content) { 312 | //Add content to the DOM before each element in the collection. 313 | //The content can be an HTML string, a DOM node or an array of nodes. 314 | let obj = getObj(content); 315 | if (isArrayThen(obj, this.before) || obj == null) { return this; } 316 | insertContent(obj, this, 317 | function (e) { e.insertAdjacentHTML('beforebegin', obj); }, 318 | function (e) { e.parentNode.insertBefore(obj, e); } 319 | ); 320 | return this; 321 | }, 322 | 323 | children: function (sel) { 324 | //Get immediate children of each element in the current collection. 325 | //If selector is given, filter the results to only include ones matching the CSS select. 326 | let elems = []; 327 | let seltype = 0; 328 | if (sel != null) { 329 | if (isType(sel, 3)) { 330 | seltype = 1; 331 | } else { 332 | seltype = 2; 333 | } 334 | } 335 | this.each(function (e) { 336 | if (seltype == 1) { 337 | //get child from index 338 | elems.push(e.children[sel]); 339 | } else { 340 | for (let x = 0; x < e.children.length; x++) { 341 | if (!seltype) { //no selector 342 | elems.push(e.children[x]); 343 | } else if (seltype == 2) { //match selector 344 | if (e.matches(sel)) { 345 | elems.push(e.children[x]); 346 | } 347 | } 348 | } 349 | } 350 | }); 351 | return clone(elems); 352 | }, 353 | 354 | closest: function (selector) { 355 | //Traverse upwards from the current element to find the first element that matches the select. 356 | return this; 357 | }, 358 | 359 | css: function (params) { 360 | //Read or set CSS properties on DOM elements. When no value is given, 361 | //returns the CSS property from the first element in the collection. 362 | //When a value is given, sets the property to that value on each element of the collection. 363 | 364 | //Multiple properties can be retrieved at once by passing an array of property names. 365 | //Multiple properties can be set by passing an object to the method. 366 | 367 | //When a value for a property is blank = function(empty string, null, or undefined), that property is removed. 368 | //When a unitless number value is given, "px" is appended to it for properties that require units. 369 | if (isType(params, 4)) { 370 | let haskeys = fals; 371 | for (let x in params) { 372 | //if params is an object with key/value pairs, apply styling to elements\ 373 | haskeys = tru; 374 | this.each(function (e) { 375 | setStyle(e, x, params[x]); 376 | }); 377 | } 378 | if (haskeys) { return this; } 379 | if (isType(params, 5)) { 380 | //if params is an array of style names, return an array of style values 381 | let vals = []; 382 | this.each(function (e) { 383 | let props = new Object(); 384 | params.forEach(function (param) { 385 | const prop = e.style[styleName(param)]; 386 | if (prop) { props[param] = prop; } 387 | }); 388 | vals.push(props); 389 | }); 390 | return vals; 391 | } 392 | } else if (isType(params, 1)) { 393 | const name = styleName(params); 394 | const arg = arguments[1]; 395 | if (isType(arg, 1)) { 396 | //set a single style property if two string arguments are supplied (key, value); 397 | this.each(function (e) { 398 | setStyle(e, name, arg); 399 | }); 400 | } else { 401 | //if params is a string, return a single style property 402 | if (this.length > 0) { 403 | 404 | if (this.length == 1) { 405 | //return a string value for one element 406 | return this[0].style[name]; 407 | } else { 408 | //return an array of strings for multiple elements 409 | let vals = []; 410 | this.each(function (e) { 411 | let val = e.style[name]; 412 | if (val == null) { val = ''; } 413 | vals.push(val); 414 | }); 415 | return vals; 416 | } 417 | } 418 | } 419 | 420 | } 421 | return this; 422 | }, 423 | 424 | each: function (func) { 425 | //Iterate through every element of the collection. Inside the iterator function, 426 | //this keyword refers to the current item = function(also passed as the second argument to the function). 427 | //If the iterator select.prototype.returns 0, iteration stops. 428 | for (let x = 0; x < this.length; x++) { 429 | func.call(this, this[x]); 430 | } 431 | return this; 432 | }, 433 | 434 | empty: function (func) { 435 | //Clear DOM contents of each element in the collection. 436 | this.each(function (e) { 437 | e.innerHTML = ''; 438 | }); 439 | return this; 440 | }, 441 | 442 | eq: function (index) { 443 | //Reduce the set of matched elements to the one at the specified index 444 | let elems = []; 445 | if (index > this.length - 1) { 446 | //out of bounds 447 | elems = []; 448 | } else if (index < 0) { 449 | //negetive index 450 | if (index * -1 >= this.length) { 451 | elems = []; 452 | } else { 453 | elems = [this[(this.length - 1) + index]]; 454 | } 455 | } else { 456 | elems = [this[index]]; 457 | } 458 | return clone(elems); 459 | }, 460 | 461 | filter: function (sel) { 462 | //Filter the collection to contain only items that match the CSS select. 463 | //If a select.prototype.is given, return only elements for which the select.prototype.returns a truthy value. 464 | let elems = []; 465 | if (isType(sel, 6)) { 466 | //filter a boolean function 467 | for (let i = 0; i < this.length; i++) { 468 | if (sel.call(this[i], i, this[i]) == tru) { elems.push(this[i]); } 469 | } 470 | } else { 471 | //filter selector string 472 | const found = query(document, sel); 473 | if (found.length > 0) { 474 | this.each(function (e) { 475 | if (found.indexOf(e) >= 0) { 476 | //make sure no duplicates are being added to the array 477 | if (elems.indexOf(e) < 0) { elems.push(e); } 478 | } 479 | }); 480 | } 481 | } 482 | return clone(elems); 483 | }, 484 | 485 | find: function (sel) { 486 | //Find elements that match CSS selector executed in scope of nodes in the current collection. 487 | let elems = []; 488 | if (this.length > 0) { 489 | this.each(function (e) { 490 | const found = query(e, sel); 491 | if (found.length > 0) { 492 | found.forEach(function (a) { 493 | //make sure no duplicates are being added to the array 494 | if (elems.indexOf(a) < 0) { elems.push(a); } 495 | }); 496 | } 497 | }); 498 | } 499 | return clone(elems); 500 | }, 501 | 502 | first: function () { 503 | //the first element found in the selector 504 | let elems = []; 505 | if (this.length > 0) { 506 | elems = [this[0]]; 507 | } 508 | return clone(elems); 509 | }, 510 | 511 | get: function (index) { 512 | //Get all elements or a single element from the current collection. 513 | //When no index is given, returns all elements in an ordinary array. 514 | //When index is specified, return only the element at that position. 515 | return this[index || 0]; 516 | }, 517 | 518 | has: function (selector) { 519 | //Filter the current collection to include only elements that have 520 | //any number of descendants that match a selector, or that contain a specific DOM node. 521 | let elems = []; 522 | if (this.length > 0) { 523 | this.each(function (e) { 524 | if (query(e, selector).length > 0) { 525 | if (elems.indexOf(e) < 0) { elems.push(e); } 526 | } 527 | }); 528 | } 529 | return clone(elems); 530 | }, 531 | 532 | hasClass: function (classes) { 533 | //Check if any elements in the collection have the specified class. 534 | let classList; 535 | if (isType(classes, 5)) { 536 | classList = classes; 537 | } else if (isType(classes, 1)) { 538 | classList = classes.split(' '); 539 | } 540 | for (let x = 0; x < this.length; x++) { 541 | const n = this[x].className || ''; 542 | if (isType(n, 1)) { 543 | const classNames = n.split(' '); 544 | if (classNames.length > 0) { 545 | if ( 546 | classList.every(function (a) { 547 | return classNames.some(function (b) { return a == b; }); 548 | }) 549 | ) { 550 | return tru; 551 | } 552 | } 553 | } 554 | } 555 | return fals; 556 | }, 557 | 558 | height: function (val) { 559 | //Get the height of the first element in the collection; 560 | //or set the height of all elements in the collection. 561 | //this function differs from jQuery as it doesn't care 562 | //about box-sizing & border when returning the height 563 | //of an element (when val is not specified). 564 | //It simply returns vanilla js offsetHeight (as it should); 565 | let obj = getObj(val); 566 | if (isType(obj, 1)) { 567 | const n = parseFloat(obj); 568 | if (!isNaN(n)) { obj = n; } else { 569 | //height is string 570 | this.each(function (e) { 571 | if (e != window && e != document) { 572 | e.style.height = obj; 573 | } 574 | }); 575 | return this; 576 | } 577 | } else if (obj == null) { 578 | if (this.length > 0) { 579 | //get height from first element 580 | const elem = this[0]; 581 | if (elem == window) { 582 | return window.innerHeight; 583 | } else if (elem == document) { 584 | const body = document.body; 585 | const html = document.documentElement; 586 | return Math.max( 587 | body.offsetHeight, 588 | body.scrollHeight, 589 | html.clientHeight, 590 | html.offsetHeight, 591 | html.scrollHeight 592 | ); 593 | } else { 594 | return elem.clientHeight; 595 | } 596 | } 597 | } else { 598 | //height is a number 599 | if (obj == 0) { 600 | this.each(function (e) { 601 | e.style.height = 0; 602 | }); 603 | } else { 604 | this.each(function (e) { 605 | e.style.height = obj + 'px'; 606 | }); 607 | } 608 | } 609 | return this; 610 | }, 611 | 612 | hide: function () { 613 | //Hide elements in this collection by setting their display CSS property to none. 614 | this.each(function (e) { 615 | e.style.display = 'none'; 616 | }); 617 | return this; 618 | }, 619 | 620 | hover: function () { 621 | const args = normalizeArgs([ 622 | { t: 1, o: tru }, //0: selector = string 623 | { t: 0, o: tru }, //1: data = anything 624 | { t: 6, o: fals }, //2: onEnter = function 625 | { t: 6, o: fals } //3: onLeave = function 626 | ], arguments); 627 | 628 | let entered = fals; 629 | this.on('mouseenter', args[0], args[1], function (e) { 630 | if (!entered) { 631 | if (args[2]) { args[2](e); } 632 | entered = tru; 633 | } 634 | }); 635 | var that = this; 636 | this.on('mouseleave', args[0], args[1], function (e) { 637 | let p = e, f = fals; 638 | while (p != null) { if (that.filter(a => a == p).length > 0) { f = tru; break; } p = p.parentNode; } 639 | if (!f) { 640 | entered = fals; 641 | if (args[3]) { args[3](e); } 642 | } 643 | }); 644 | }, 645 | 646 | html: function (content) { 647 | //Get or set HTML contents of elements in the collection. 648 | //When no content given, returns innerHTML of the first element. 649 | //When content is given, use it to replace contents of each element. 650 | let obj = getObj(content); 651 | if (obj == null) { 652 | if (this.length > 0) { 653 | return this[0].innerHTML; 654 | } else { 655 | return ''; 656 | } 657 | } else { 658 | this.each(function (e) { 659 | e.innerHTML = obj; 660 | }); 661 | } 662 | return this; 663 | }, 664 | 665 | /** 666 | * @suppress {checkTypes} 667 | */ 668 | index: function (e) { 669 | //Get the position of an element. When no element is given, 670 | //returns position of the current element among its siblings. 671 | //When an element is given, returns its position in the current collection. 672 | //Returns -1 if not found. 673 | let i = -1; 674 | if (this.length > 0) { 675 | const elem = e ? e : this[0]; 676 | const p = elem.parentNode; 677 | let c; 678 | if (p) { 679 | c = p.children; 680 | if ([].indexOf) { 681 | return [].indexOf.call(c, elem); 682 | } else { 683 | //fallback for older browsers 684 | for (let x = 0; x < c.length; x++) { 685 | if (c[x] == elem) { 686 | return x; 687 | } 688 | } 689 | } 690 | } 691 | } 692 | return i; 693 | }, 694 | 695 | innerHeight: function (height) { 696 | //Get the current computed inner height (including padding but not border) for the 697 | //first element in the set of matched elements or set the inner height of every matched element 698 | let obj = getObj(height); 699 | if (obj == null) { 700 | //get inner height of first element (minus padding) 701 | if (this.length > 0) { 702 | const e = this[0]; 703 | const style = getComputedStyle(e); 704 | let padtop = parseFloat(style.paddingTop); 705 | let padbot = parseFloat(style.paddingBottom); 706 | if (isNaN(padtop)) { padtop = 0; } 707 | if (isNaN(padbot)) { padbot = 0; } 708 | return e.clientHeight - (padtop + padbot); 709 | } 710 | } else { 711 | //set height of elements 712 | return this.height(height); 713 | } 714 | }, 715 | 716 | innerWidth: function (width) { 717 | //Get the current computed inner width (including padding but not border) for the 718 | //first element in the set of matched elements or set the inner width of every matched element 719 | let obj = getObj(width); 720 | if (obj == null) { 721 | //get inner width of first element (minus padding) 722 | if (this.length > 0) { 723 | const e = this[0]; 724 | const style = getComputedStyle(e); 725 | let padright = parseFloat(style.paddingRight); 726 | let padleft = parseFloat(style.paddingLeft); 727 | if (isNaN(padright)) { padright = 0; } 728 | if (isNaN(padleft)) { padleft = 0; } 729 | return e.clientWidth - (padright + padleft); 730 | } 731 | } else { 732 | //set width of elements 733 | return this.width(width); 734 | } 735 | }, 736 | 737 | is: function (selector) { 738 | //Check if all the elements of the current collection matches the CSS select. 739 | if (this.length > 0) { 740 | const self = this; 741 | let obj = getObj(selector); 742 | for (let x = 0; x < this.length; x++) { 743 | switch (obj) { 744 | case ':focus': 745 | if (this[x] == document.activeElement) { 746 | return tru; 747 | } 748 | break; 749 | default: 750 | const q = query(this[x].parentNode, obj); 751 | if (q.some(function (a) { return a == self[0] })) { 752 | return tru; 753 | } 754 | break; 755 | } 756 | } 757 | 758 | } 759 | return fals; 760 | }, 761 | 762 | last: function () { 763 | //Get the last element of the current collection. 764 | let elems = []; 765 | if (this.length > 0) { 766 | elems = [this[this.length - 1]]; 767 | } 768 | return clone(elems); 769 | }, 770 | 771 | map: function (func) { //func(index, element) 772 | //Iterate through every element of the collection. Inside the iterator function, 773 | //this keyword refers to the current item = function(also passed as the second argument to the function). 774 | //If the iterator select.prototype.returns 0, iteration stops. 775 | let mapped = []; 776 | for (let x = 0; x < this.length; x++) { 777 | mapped.push(func(x, this[x])); 778 | } 779 | return mapped; 780 | }, 781 | 782 | next: function (selector) { 783 | //Get the next sibling optionally filtered by selector of each element in the collection. 784 | let elems = []; 785 | this.each(function (e) { 786 | let el = e.nextSibling; 787 | if (selector && el) { 788 | //use selector 789 | const q = query(e.parentNode, selector); 790 | while (el != null) { 791 | if (el.nodeName != '#text') { 792 | if (q.some(function (s) { return s == el })) { 793 | elems.push(el); 794 | break; 795 | } 796 | } 797 | el = el.nextSibling; 798 | } 799 | } else if (el) { 800 | //no selector 801 | while (el != null) { 802 | if (el.nodeName != '#text') { 803 | elems.push(el); 804 | break; 805 | } 806 | el = el.nextSibling; 807 | } 808 | } 809 | }); 810 | return clone(elems); 811 | }, 812 | 813 | nextAll: function (selector) { 814 | //Get all siblings below current sibling optionally filtered by selector of each element in the collection. 815 | let elems = []; 816 | if (selector) { 817 | //use selector 818 | this.each(function (e) { 819 | const q = query(e, selector); 820 | let n = e.nextSibling; 821 | while (n) { 822 | while (n.nodeName == '#text') { 823 | n = n.nextSibling; 824 | if (!n) { break; } 825 | } 826 | if (!n) { break; } 827 | if (q.some(function (s) { return s == n; })) { elems.push(n); } 828 | n = n.nextSibling; 829 | } 830 | }); 831 | } else { 832 | //no selector 833 | this.each(function (e) { 834 | let n = e.nextSibling; 835 | while (n) { 836 | while (n.nodeName == '#text') { 837 | n = n.nextSibling; 838 | if (!n) { break; } 839 | } 840 | if (!n) { break; } 841 | elems.push(n); 842 | n = n.nextSibling; 843 | } 844 | }); 845 | } 846 | return clone(elems); 847 | }, 848 | 849 | not: function (selector) { 850 | //Filter the current collection to get a new collection of elements that don't match the CSS select. 851 | //If another collection is given instead of selector, return only elements not present in it. 852 | //If a select.prototype.is given, return only elements for which the select.prototype.returns a falsy value. 853 | //Inside the function, the this keyword refers to the current element. 854 | const sel = getObj(selector); 855 | let elems = this; 856 | //check if selector is an array (of selectors) 857 | if (isType(sel, 5)) { 858 | sel.forEach(function (s) { 859 | const q = query(document, s); 860 | elems = diffArray(elems, q); 861 | }); 862 | this.push(elems); 863 | return this; 864 | } 865 | return clone(diffArray(elems, query(document, sel))); 866 | }, 867 | 868 | off: function () { 869 | //remove an event handler 870 | let args = normalizeArgs([ 871 | { t: 1, o: fals }, //0: event = string 872 | { t: 1, o: tru }, //1: selector = string (optional) 873 | { t: 6, o: fals } //2: handler = function 874 | ], arguments); 875 | this.each(function (e) { 876 | for (let x = 0; x < listeners.length; x++) { 877 | if (listeners[x].elem == e) { 878 | //found element in listeners array, now find specific function (func) 879 | const item = listeners[x]; 880 | if (args[2] == null) { 881 | //if no function specified, remove all listeners for a specific event 882 | if (args[0] == null) { 883 | //remove all events and functions for element from listener 884 | for (let y = 0; y < item.events.length; y++) { 885 | const ev = item.events[y]; 886 | for (let z = 0; z < ev.list.length; z++) { 887 | e.removeEventListener(ev.name, ev.list[z][1], tru); 888 | } 889 | } 890 | listeners.splice(x, 1); 891 | } else { 892 | //remove all functions (for event) from element in listener 893 | for (let y = 0; y < item.events.length; y++) { 894 | if (item.events[y].name == args[0]) { 895 | const ev = item.events[y]; 896 | for (let z = 0; z < ev.list.length; z++) { 897 | e.removeEventListener(args[0], ev.list[z][1], tru); 898 | } 899 | listeners[x].events.splice(y, 1); 900 | if (listeners[x].events.length == 0) { 901 | //remove element from listeners array since no more events exist for the element 902 | listeners.splice(x, 1); 903 | } 904 | break; 905 | } 906 | } 907 | } 908 | } else { 909 | //remove specific listener based on event & function 910 | for (let y = 0; y < item.events.length; y++) { 911 | if (item.events[y].name == args[0]) { 912 | //remove specific event from element in listeners array 913 | const ev = item.events[y]; 914 | for (let z = 0; z < ev.list.length; z++) { 915 | if (ev.list[z][1].toString() === args[2].toString() //check function match 916 | && ev.list[z][0] == args[1]) { //check selector match 917 | e.removeEventListener(args[0], args[2], tru); 918 | listeners[x].events[y].list.splice(z, 1); 919 | break; 920 | } 921 | } 922 | 923 | if (listeners[x].events[y].list.length == 0) { 924 | //remove event from element list array since no more functions exist for the event 925 | listeners[x].events.splice(y, 1); 926 | if (listeners[x].events.length == 0) { 927 | //remove element from listeners array since no more events exist for the element 928 | listeners.splice(x, 1); 929 | } 930 | } 931 | break; 932 | } 933 | } 934 | } 935 | break; 936 | } 937 | } 938 | }); 939 | return this; 940 | }, 941 | 942 | offset: function () { 943 | //Get position of the element in the document. 944 | //Returns an object with properties: top, left, width and height. 945 | 946 | //When given an object with properties left and top, use those values to 947 | //position each element in the collection relative to the document. 948 | if (this.length > 0) { 949 | const box = this[0].getBoundingClientRect(); 950 | return { 951 | left: box.left + document.body.scrollLeft, 952 | top: box.top + document.body.scrollTop 953 | }; 954 | } 955 | return { left: 0, top: 0 }; 956 | }, 957 | 958 | offsetParent: function () { 959 | //Find the first ancestor element that is positioned, 960 | //meaning its CSS position value is "relative", "absolute"" or "fixed". 961 | if (this.length > 0) { 962 | return this[0].offsetParent; 963 | } 964 | return null; 965 | }, 966 | 967 | on: function () { 968 | //Attach an event handler function for one or more events to the selected elements. 969 | let args = normalizeArgs([ 970 | { t: 1, o: fals }, //0: event = string 971 | { t: 1, o: tru }, //1: selector = string (optional) 972 | { t: 0, o: tru }, //2: data = anything (optional) 973 | { t: 6, o: fals } //3: handler = function 974 | ], arguments); 975 | const events = args[0].replace(/\s/g, '').split(','); 976 | for (let i = 0; i < events.length; i++) { 977 | const ev = events[i]; 978 | if (ev == "hover") { 979 | this.hover(args[1], args[2], args[3], args[3]); 980 | } else { 981 | this.each(function (e) { 982 | let params = [args[1], args[3]]; 983 | if (args[1] != null && args[1] != '') { 984 | function delegate(el) { 985 | const sels = query(e, args[1]); 986 | for (let x = 0; x < sels.length; x++) { 987 | if (el.target == sels[x]) { 988 | args[3].apply(sels[x], [].slice.call(arguments)); 989 | } 990 | } 991 | } 992 | params = [args[1], delegate]; 993 | e.addEventListener(ev, delegate, tru); 994 | } else { 995 | e.addEventListener(ev, args[3], tru); 996 | } 997 | 998 | let listen = fals; 999 | for (let x = 0; x < listeners.length; x++) { 1000 | if (listeners[x].elem == e) { 1001 | //found element, now find specific event 1002 | const events = listeners[x].events; 1003 | let f = fals; 1004 | for (let y = 0; y < events.length; y++) { 1005 | if (events[y].name == ev) { 1006 | //found existing event in list 1007 | listeners[x].events[y].list.push(params); 1008 | f = tru; 1009 | break; 1010 | } 1011 | } 1012 | if (f == fals) { 1013 | //event doesn't exist yet 1014 | listeners[x].events.push({ name: ev, list: [params] }); 1015 | } 1016 | listen = tru; 1017 | break; 1018 | } 1019 | } 1020 | if (listen == fals) { listeners.push({ elem: e, events: [{ name: ev, list: [params] }] }); } 1021 | }); 1022 | } 1023 | } 1024 | return this; 1025 | }, 1026 | 1027 | //TODO: one 1028 | one: function (event, func) { 1029 | //Attach a handler to an event for the elements. The handler is executed at most once per element per event type 1030 | }, 1031 | 1032 | //TODO: outerHeight 1033 | outerHeight: function () { 1034 | 1035 | }, 1036 | 1037 | //TODO: outerWidth 1038 | outerWidth: function () { 1039 | 1040 | }, 1041 | 1042 | parent: function (selector) { 1043 | //Get immediate parents of each element in the collection. 1044 | //If CSS selector is given, filter results to include only ones matching the select. 1045 | let elems = []; 1046 | this.each(function (e) { 1047 | const el = e.parentNode; 1048 | if (selector == null || selector == '') { 1049 | if (elems.indexOf(el) < 0) { 1050 | elems.push(el); 1051 | } 1052 | } else if (el.matches(selector)) { 1053 | if (elems.indexOf(el) < 0) { 1054 | elems.push(el); 1055 | } 1056 | } 1057 | 1058 | }); 1059 | return clone(elems); 1060 | }, 1061 | 1062 | parents: function (selector) { 1063 | //Get all ancestors of each element in the selector. 1064 | //If CSS selector is given, filter results to include only ones matching the select. 1065 | let elems = []; 1066 | this.each(function (e) { 1067 | let el = e.parentNode; 1068 | while (el) { 1069 | if (selector == null || selector == '') { 1070 | if (elems.indexOf(el) < 0) { 1071 | elems.push(el); 1072 | } 1073 | } else { 1074 | if (el.matches) { 1075 | if (el.matches(selector)) { 1076 | if (elems.indexOf(el) < 0) { 1077 | elems.push(el); 1078 | } 1079 | } 1080 | } else if (el.matchesSelector) { 1081 | if (el.matchesSelector(selector)) { 1082 | if (elems.indexOf(el) < 0) { 1083 | elems.push(el); 1084 | } 1085 | } 1086 | } 1087 | } 1088 | el = el.parentNode; 1089 | } 1090 | }); 1091 | return clone(elems); 1092 | }, 1093 | 1094 | position: function () { 1095 | //Get the position of the first element in the collection, relative to the offsetParent. 1096 | //This information is useful when absolutely positioning an element to appear aligned with another. 1097 | if (this.length > 0) { 1098 | return { left: this[0].offsetLeft, top: this[0].offsetTop }; 1099 | } 1100 | return { left: 0, top: 0 }; 1101 | }, 1102 | 1103 | prepend: function (content) { 1104 | //Prepend content to the DOM inside each element in the collection. 1105 | //The content can be an HTML string, a DOM node or an array of nodes. 1106 | let obj = getObj(content); 1107 | if (isArrayThen(obj, this.append) || obj == null) { return this; } 1108 | 1109 | 1110 | insertContent(obj, this, 1111 | function (e) { e.insertAdjacentHTML('afterbegin', obj); }, 1112 | function (e) { e.insertBefore(obj, e.firstChild); } 1113 | ); 1114 | return this; 1115 | }, 1116 | 1117 | prev: function (selector) { 1118 | //Get the previous sibling optionally filtered by selector of each element in the collection. 1119 | let elems = []; 1120 | this.each(function (e) { 1121 | let el = e.previousSibling; 1122 | if (selector && el) { 1123 | //use selector 1124 | const q = query(e.parentNode, selector); 1125 | while (el != null) { 1126 | if (el.nodeName != '#text') { 1127 | if (q.some(function (s) { return s == el })) { 1128 | elems.push(el); 1129 | break; 1130 | } 1131 | } 1132 | el = el.previousSibling; 1133 | } 1134 | } else if (el) { 1135 | //no selector 1136 | while (el != null) { 1137 | if (el.nodeName != '#text') { 1138 | elems.push(el); 1139 | break; 1140 | } 1141 | el = el.previousSibling; 1142 | } 1143 | } 1144 | }); 1145 | return clone(elems); 1146 | }, 1147 | 1148 | prop: function (name, val) { 1149 | //Read or set properties of DOM elements. This should be preferred over attr in case of 1150 | //reading values of properties that change with user interaction over time, such as checked and selected. 1151 | const n = getObj(name); 1152 | let v = getObj(val); 1153 | if (isType(n, 5)) { 1154 | //get multiple properties from the first element 1155 | let props = {}; 1156 | n.forEach(function (p) { 1157 | props[p] = this.prop(p); 1158 | }); 1159 | return props; 1160 | } 1161 | 1162 | const execAttr = function (a, b) { 1163 | //get / set / remove DOM attribute 1164 | if (v != null) { 1165 | if (v == '--') { 1166 | //remove 1167 | this.each(function (e) { 1168 | e.removeAttribute(a); 1169 | }); 1170 | } else { 1171 | //set 1172 | if (v == fals) { 1173 | this.each(function (e) { 1174 | e.removeAttribute(a); 1175 | }); 1176 | } else { 1177 | this.attr(a, b); 1178 | } 1179 | } 1180 | } else { 1181 | //get 1182 | if (this.length > 0) { 1183 | return this[0].getAttribute(a) || ''; 1184 | } 1185 | } 1186 | }; 1187 | 1188 | const execProp = function (a) { 1189 | if (v != null) { 1190 | if (v == '--') { 1191 | //remove 1192 | this.each(function (e) { 1193 | e.style.removeProperty(a); 1194 | }); 1195 | } else { 1196 | //set 1197 | v = v == 0 ? fals : tru; 1198 | this.each(function (e) { 1199 | e.style.setProperty(a, v); 1200 | }); 1201 | } 1202 | 1203 | } else { 1204 | //get 1205 | if (this.length > 0) { 1206 | let e = this[0]; 1207 | let b = e[a]; 1208 | if (b == null) { 1209 | b = e.getAttribute(a) != null ? tru : fals; 1210 | e[a] = b; 1211 | } 1212 | return b; 1213 | } 1214 | } 1215 | }; 1216 | 1217 | //get, set, or remove (if val == '--') a specific property from element(s) 1218 | let nn = ''; 1219 | switch (n) { 1220 | case "defaultChecked": 1221 | nn = 'checked'; 1222 | break; 1223 | case "checked": 1224 | if (!v) { if (this.length > 0) { return this[0].checked; } } 1225 | break; 1226 | case "defaultSelected": 1227 | nn = 'selected'; 1228 | break; 1229 | case "selected": 1230 | break; 1231 | case "defaultDisabled": 1232 | nn = 'disabled'; 1233 | break; 1234 | case "disabled": 1235 | //get/set/remove boolean property that belongs to the DOM element object or is an attribute (default) 1236 | break; 1237 | 1238 | case "selectedIndex": 1239 | if (v != null) { 1240 | if (v === parseInt(v, 10)) { 1241 | this.each(function (e) { 1242 | if (e.nodeType == 'SELECT') { 1243 | e.selectedIndex = v; 1244 | } 1245 | }); 1246 | } 1247 | } 1248 | break; 1249 | return; 1250 | 1251 | case "nodeName": 1252 | if (val != null) { 1253 | //set node name 1254 | //TODO: replace DOM element with new element of new node name, cloning all attributes & appending all children elements 1255 | return; 1256 | } else { 1257 | //get node name 1258 | if (this.length > 0) { 1259 | return this[0].nodeName; 1260 | } else { 1261 | return ''; 1262 | } 1263 | } 1264 | break; 1265 | case "tagName": 1266 | if (val != null) { 1267 | //set node name 1268 | //TODO: replace DOM element with new element of new tag name, cloning all attributes & appending all children elements 1269 | return; 1270 | } else { 1271 | //get tag name 1272 | if (this.length > 0) { 1273 | return this[0].tagName; 1274 | } else { 1275 | return ''; 1276 | } 1277 | } 1278 | break; 1279 | 1280 | default: 1281 | // last resort to get/set/remove property value from style or attribute 1282 | //first, try getting a style 1283 | let a = execProp.call(this, n); 1284 | if (a != null && typeof a != 'undefined') { 1285 | return a; 1286 | } else { 1287 | //next, try getting a attribute 1288 | a = execAttr.call(this, n, v); 1289 | if (a != null) { 1290 | return a; 1291 | } 1292 | } 1293 | break; 1294 | } 1295 | if (nn != '') { 1296 | //get/set/remove default property 1297 | const a = execAttr.call(this, nn, nn); 1298 | if (a != null) { return a; } 1299 | } else { 1300 | //get/set/remove property 1301 | const a = execProp.call(this, n); 1302 | if (a != null) { return a; } 1303 | } 1304 | 1305 | return this; 1306 | }, 1307 | 1308 | push: function (elems) { 1309 | [].push.apply(this, elems); 1310 | return this; 1311 | }, 1312 | 1313 | ready: function (callback) { 1314 | if (this.length == 1) { 1315 | if (this[0] == document) { 1316 | if (document.readyState != 'loading') { 1317 | callback(); 1318 | } else { 1319 | document.addEventListener('DOMContentLoaded', callback); 1320 | } 1321 | } 1322 | } 1323 | }, 1324 | 1325 | remove: function (selector) { 1326 | //Remove the set of matched elements from the DOM 1327 | this.each(function (e) { 1328 | e.parentNode.removeChild(e); 1329 | }); 1330 | this.push([]); 1331 | return this; 1332 | }, 1333 | 1334 | removeAttr: function (attr) { 1335 | //Remove an attribute from each element in the set of matched elements 1336 | let obj = getObj(attr); 1337 | if (isType(obj, 5)) { 1338 | obj.forEach(function (a) { 1339 | this.each(function (e) { 1340 | e.removeAttribute(a); 1341 | }); 1342 | }); 1343 | } else if (typeof obj == 'string') { 1344 | this.each(function (e) { 1345 | e.removeAttribute(obj); 1346 | }); 1347 | } 1348 | 1349 | return this; 1350 | }, 1351 | 1352 | removeClass: function (className) { 1353 | //Remove a single class, multiple classes, or all classes from each element in the set of matched elements 1354 | let obj = getObj(className); 1355 | if (typeof obj == 'string') { 1356 | //check for class name array 1357 | obj = obj.replace(/\,/g, ' ').replace(/\s\s/g, ' '); 1358 | if (obj.indexOf(' ') > 0) { 1359 | obj = obj.split(' '); 1360 | } 1361 | } 1362 | if (isType(obj, 5)) { 1363 | this.each(function (e) { 1364 | obj.forEach(function (a) { 1365 | if (e.className) { 1366 | e.className = e.className.split(' ').filter(function (b) { return b != '' && b != a; }).join(' '); 1367 | } 1368 | }); 1369 | }); 1370 | } else if (typeof obj == 'string') { 1371 | this.each(function (e) { 1372 | if (e.className) { 1373 | e.className = e.className.split(' ').filter(function (b) { return b != '' && b != obj; }).join(' '); 1374 | } 1375 | }); 1376 | } 1377 | return this; 1378 | }, 1379 | 1380 | removeProp: function (name) { 1381 | //Remove a property for the set of matched elements 1382 | this.prop(name, '--'); 1383 | return this; 1384 | }, 1385 | 1386 | serialize: function () { 1387 | if (this.length == 0) { return ''; } 1388 | let form = this[0]; 1389 | if (!form || form.nodeName !== "FORM") { 1390 | return ''; 1391 | } 1392 | let i, j, q = []; 1393 | for (i = form.elements.length - 1; i >= 0; i = i - 1) { 1394 | if (form.elements[i].name === "") { 1395 | continue; 1396 | } 1397 | switch (form.elements[i].nodeName) { 1398 | case 'INPUT': 1399 | switch (form.elements[i].type) { 1400 | case 'text': 1401 | case 'hidden': 1402 | case 'password': 1403 | case 'button': 1404 | case 'reset': 1405 | case 'submit': 1406 | q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value)); 1407 | break; 1408 | case 'checkbox': 1409 | case 'radio': 1410 | if (form.elements[i].checked) { 1411 | q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value)); 1412 | } 1413 | break; 1414 | } 1415 | break; 1416 | case 'file': 1417 | break; 1418 | case 'TEXTAREA': 1419 | q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value)); 1420 | break; 1421 | case 'SELECT': 1422 | switch (form.elements[i].type) { 1423 | case 'select-one': 1424 | q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value)); 1425 | break; 1426 | case 'select-multiple': 1427 | for (j = form.elements[i].options.length - 1; j >= 0; j = j - 1) { 1428 | if (form.elements[i].options[j].selected) { 1429 | q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].options[j].value)); 1430 | } 1431 | } 1432 | break; 1433 | } 1434 | break; 1435 | case 'BUTTON': 1436 | switch (form.elements[i].type) { 1437 | case 'reset': 1438 | case 'submit': 1439 | case 'button': 1440 | q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value)); 1441 | break; 1442 | } 1443 | break; 1444 | } 1445 | } 1446 | return q.join("&"); 1447 | }, 1448 | 1449 | show: function () { 1450 | //Display the matched elements 1451 | this.removeClass('hide'); 1452 | this.each(function (e) { 1453 | e.style.display = 'block'; 1454 | }); 1455 | return this; 1456 | }, 1457 | 1458 | siblings: function (selector) { 1459 | //Get the siblings of each element in the set of matched elements, optionally filtered by a selector 1460 | let elems = []; 1461 | let sibs = []; 1462 | let q = []; 1463 | const sel = getObj(selector); 1464 | const add = function (e) { 1465 | if (!elems.some(function (a) { return a == e })) { elems.push(e); } 1466 | } 1467 | const find = function (e, s) { 1468 | //find siblings 1469 | if (s != null) { 1470 | q = query(e.parentNode, s); 1471 | } 1472 | sibs = e.parentNode.children; 1473 | for (let x = 0; x < sibs.length; x++) { 1474 | const sib = sibs[x]; 1475 | if (sib != e) { 1476 | if (s != null) { 1477 | if (q.some(function (a) { return a == sib; })) { 1478 | add(sib); 1479 | } 1480 | } else { 1481 | add(sib); 1482 | } 1483 | } 1484 | } 1485 | }; 1486 | 1487 | if (sel != null) { 1488 | if (isType(sel, 5)) { 1489 | this.each(function (e) { 1490 | sel.forEach(function (s) { 1491 | find(e, s); 1492 | }); 1493 | }); 1494 | } else { 1495 | this.each(function (e) { 1496 | find(e, sel); 1497 | }); 1498 | } 1499 | } else { 1500 | this.each(function (e) { 1501 | find(e, null); 1502 | }); 1503 | } 1504 | return clone(elems); 1505 | }, 1506 | 1507 | //TODO: slice 1508 | slice: function () { 1509 | //Reduce the set of matched elements to a subset specified by a range of indices 1510 | [].slice.apply(this, arguments); 1511 | return this; 1512 | }, 1513 | 1514 | splice: function () { 1515 | [].splice.apply(this, arguments); 1516 | }, 1517 | 1518 | stop: function () { 1519 | if (typeof (Velocity) != 'undefined') { 1520 | Velocity(this, "stop"); 1521 | } 1522 | return this; 1523 | }, 1524 | 1525 | //TODO: text 1526 | text: function () { 1527 | //Get the combined text contents of each element in the set of matched elements, including their descendants, or set the text contents of the matched elements 1528 | return ''; 1529 | }, 1530 | 1531 | toggle: function () { 1532 | //Display or hide the matched elements 1533 | this.each(function (e) { 1534 | if (e.style.display == 'none') { 1535 | e.style.display = ''; 1536 | } else { e.style.display = 'none'; } 1537 | }); 1538 | return this; 1539 | }, 1540 | 1541 | toggleClass: function (className) { 1542 | //Add or remove one or more classes from each element in the set of matched elements, depending on either the class' presence or the value of the state argument 1543 | let obj = getObj(className); 1544 | if (typeof obj == 'string') { 1545 | obj = obj.split(' '); 1546 | } 1547 | if (isType(obj, 5)) { 1548 | this.each(function (e) { 1549 | let c = e.className; 1550 | let b = -1; 1551 | if (c != null && c != '') { 1552 | c = c.split(' '); 1553 | //array of class names 1554 | for (var x = 0; x < obj.length; x++) { 1555 | var a = obj[x]; 1556 | b = c.indexOf(a); 1557 | if (b >= 0) { 1558 | //remove class 1559 | c.splice(b, 1); 1560 | } else { 1561 | //add class 1562 | c.push(a); 1563 | } 1564 | } 1565 | //update element className attr 1566 | e.className = c.join(' '); 1567 | } else { 1568 | e.className = className; 1569 | } 1570 | }); 1571 | } 1572 | }, 1573 | 1574 | val: function (value) { 1575 | //Get the current value of the first element in the set of matched elements or set the value of every matched element 1576 | if (value != null) { 1577 | this.each(function (a) { 1578 | a.value = value; 1579 | }); 1580 | } else { 1581 | if (this.length > 0) { 1582 | return this[0].value; 1583 | } 1584 | return ''; 1585 | } 1586 | return this; 1587 | }, 1588 | 1589 | width: function (val) { 1590 | //Get the current computed width for the first element in the set of matched elements or set the width of every matched element 1591 | let obj = getObj(val); 1592 | if (isType(obj, 1)) { 1593 | const n = parseFloat(obj); 1594 | if (!isNaN(n)) { obj = n; } else { 1595 | //width is string 1596 | this.each(function (e) { 1597 | if (e != window && e != document) { 1598 | e.style.width = obj; 1599 | } 1600 | }); 1601 | return this; 1602 | } 1603 | } else if (obj == null) { 1604 | if (this.length > 0) { 1605 | //get width from first element 1606 | const elem = this[0]; 1607 | if (elem == window) { 1608 | return window.innerWidth; 1609 | } else if (elem == document) { 1610 | const body = document.body; 1611 | const html = document.documentElement; 1612 | return Math.max( 1613 | body.offsetWidth, 1614 | body.scrollWidth, 1615 | html.clientWidth, 1616 | html.offsetWidth, 1617 | html.scrollWidth 1618 | ); 1619 | } else { 1620 | return elem.clientWidth; 1621 | } 1622 | } 1623 | } else { 1624 | //width is a number 1625 | if (obj == 0) { 1626 | this.each(function (e) { 1627 | e.style.width = 0; 1628 | }); 1629 | } else { 1630 | this.each(function (e) { 1631 | e.style.width = obj + 'px'; 1632 | }); 1633 | } 1634 | } 1635 | return this; 1636 | }, 1637 | 1638 | //TODO: wrap 1639 | wrap: function (elem) { 1640 | //Wrap an HTML structure around each element in the set of matched elements 1641 | return this; 1642 | }, 1643 | 1644 | //TODO: wrapAll 1645 | wrapAll: function (elem) { 1646 | //Wrap an HTML structure around all elements in the set of matched elements 1647 | return this; 1648 | }, 1649 | 1650 | //TODO: wrapInner 1651 | wrapInner: function (elem) { 1652 | //Wrap an HTML structure around the content of each element in the set of matched elements 1653 | return this; 1654 | } 1655 | }; 1656 | 1657 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 1658 | // create public selector object ////////////////////////////////////////////////////////////////////////////////// 1659 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 1660 | /** @noalias */ 1661 | window['$'] = function(selector) { 1662 | return new select(selector); 1663 | } 1664 | 1665 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 1666 | // add functionality to the $ object ////////////////////////////////////////////////////////////////////////////// 1667 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 1668 | /** @noalias */ 1669 | window['$'].ajax = function () { 1670 | let args = normalizeArgs([ 1671 | { t: 1, o: tru }, //0: url = string (optional) 1672 | { t: 4, o: tru }, //1: settings = object (optional) 1673 | ], arguments); 1674 | args[1] = getObj(args[1]); 1675 | var opt = args[1] || { url: args[0] }; 1676 | opt.url = args[0] || opt.url; 1677 | opt.async = opt.async || tru; 1678 | opt.cache = opt.cache || fals; 1679 | opt.contentType = opt.contentType || 'application/x-www-form-urlencoded; charset=UTF-8'; 1680 | opt.data = opt.data || ''; 1681 | opt.dataType = opt.dataType || ''; 1682 | opt.method = opt.method || "GET"; 1683 | opt.type = opt.method || opt.type; 1684 | 1685 | //set up AJAX request 1686 | var req = new XMLHttpRequest(); 1687 | 1688 | //set up callbacks 1689 | req.onload = function () { 1690 | if (req.status >= 200 && req.status < 400) { 1691 | //request success 1692 | let resp = req.responseText; 1693 | if (opt.dataType.toLowerCase() == "json") { 1694 | resp = JSON.parse(resp); 1695 | } 1696 | if (opt.success) { 1697 | opt.success(resp, req.statusText, req); 1698 | } 1699 | if (opt.complete) { 1700 | opt.complete(resp, req.statusText, req); 1701 | } 1702 | } else { 1703 | //connected to server, but returned an error 1704 | if (opt.error) { 1705 | opt.error(req, req.statusText); 1706 | } 1707 | } 1708 | ajaxWait = false; 1709 | runAjaxQueue(); 1710 | }; 1711 | 1712 | req.onerror = function () { 1713 | //an error occurred before connecting to server 1714 | if (opt.error) { 1715 | opt.error(req, req.statusText); 1716 | } 1717 | ajaxWait = false; 1718 | runAjaxQueue(); 1719 | }; 1720 | 1721 | if (opt.beforeSend) { 1722 | if (opt.beforeSend(req, opt) == fals) { 1723 | //canceled ajax call before sending 1724 | return fals; 1725 | } 1726 | } 1727 | 1728 | //finally, add AJAX request to queue 1729 | ajaxQueue.unshift({ req: req, opt: opt }); 1730 | runAjaxQueue(); 1731 | } 1732 | 1733 | window['$'].getJSON = function (url, complete, error) { 1734 | $.ajax(url, { dataType:'json', complete: complete, error: error }); 1735 | } 1736 | 1737 | function runAjaxQueue() { 1738 | //run next request in the queue 1739 | if (ajaxWait == true) { return; } 1740 | if (ajaxQueue.length == 0) { return; } 1741 | ajaxWait = true; 1742 | let queue = ajaxQueue[ajaxQueue.length - 1]; 1743 | let req = queue.req; 1744 | let opt = queue.opt; 1745 | 1746 | //remove from queue 1747 | ajaxQueue.pop(); 1748 | 1749 | //run AJAX request from queue 1750 | req.open(opt.method, opt.url, opt.async, opt.username, opt.password); 1751 | req.setRequestHeader('Content-Type', opt.contentType); 1752 | req.send(opt.data); 1753 | } 1754 | 1755 | /** @noalias */ 1756 | /** 1757 | * @param {...string|boolean} var_args 1758 | */ 1759 | window['$'].extend = function (var_args) { 1760 | let extended = {}; 1761 | let deep = fals; 1762 | let i = 0; 1763 | const length = arguments.length; 1764 | 1765 | // Check if a deep merge 1766 | if (Object.prototype.toString.call(arguments[0]) === '[object Boolean]') { 1767 | deep = arguments[0]; 1768 | i++; 1769 | } 1770 | 1771 | // Merge the object into the extended object 1772 | const merge = function (obj) { 1773 | for (let prop in obj) { 1774 | if (Object.prototype.hasOwnProperty.call(obj, prop)) { 1775 | // If deep merge and property is an object, merge properties 1776 | if (deep && Object.prototype.toString.call(obj[prop]) === '[object Object]') { 1777 | extended[prop] = window['$'].extend(1, extended[prop], obj[prop]); 1778 | } else { 1779 | extended[prop] = obj[prop]; 1780 | } 1781 | } 1782 | } 1783 | }; 1784 | 1785 | // Loop through each object and conduct a merge 1786 | for (; i < length; i++) { 1787 | let obj = arguments[i]; 1788 | merge(obj); 1789 | } 1790 | 1791 | return extended; 1792 | 1793 | }; 1794 | 1795 | })(); -------------------------------------------------------------------------------- /dist/selector.min.js: -------------------------------------------------------------------------------- 1 | !function(){const t=!0,e=!1,n=document,i=["top","right","bottom","left","width","height","minWidth","minHeight","maxWidth","maxHeight","fontSize"],s=["border","padding","margin"],l=[],o=/^\.[\w-]*$/,r=/^\w+$/;let u=[],c=!1;function h(t){return t&&this.push(f(document,t)),this}function f(t,e){if(null==t)return[];let i=[];if(b(e,4))i=b(e,5)?e:[e];else if(null!=e&&""!=e){t=t||n;const s=o.test(e)?t.getElementsByClassName(e.slice(1)):r.test(e)?t.getElementsByTagName(e):t.querySelectorAll(e);for(let t=s.length;t--;i.unshift(s[t]));}return i}function a(t){if(t.indexOf("-")<0)return t;const e=t.split("-");return e.length>1&&(e[1]=e[1][0].toUpperCase()+e[1].substr(1)),e.join("")}function d(t,e,n){if("#text"==t.nodeName)return;let l=n;""!==l&&null!==l?((Number(l)==l||0===l)&&l.toString().indexOf("%")<0&&(i.indexOf(e)>=0?l=n+"px":!0===s.some(function(t){return 0==e.indexOf(t)})&&(l=n+"px")),t.style[e]=l):t.style[e]=""==l?null:l}function p(t){return null==t?null:b(t,1)?t:b(t,5)?t[0]:b(t,6)?p(t()):t}function m(t,e){return t.filter(function(t){return!e.includes(t)})}function g(n,i){if(b(n,5)){for(let t in n)i.call(this,n[t]);return t}return e}function b(n,i){if(null!=n)switch(i){case 0:return t;case 1:return"string"==typeof n;case 2:return"boolean"==typeof n;case 3:return!isNaN(parseFloat(n))&&isFinite(n);case 4:return"object"==typeof n;case 5:return"function"==typeof n.splice;case 6:return"function"==typeof n}return e}function y(n,i){let s,l,o=[],r=[].slice.call(i),u=n.length-1;for(let i=r.length-1;i>=0;i--)for(let c=u;c>=0;c--){if(l=e,n[c].o==t){s=0;for(let t=0;t<=c;t++)n[t].o==e&&s++;l=s>i}if(l==e&&(l=!b(r[i],n[c].t)&&null!=r[i]),o[c]=l?null:r[i],u=c-1,!l||null==r[i])break}return o}function v(e,n,i,s){if(b(e,1)==t)for(let t=0;t0){const e=t.split(" ");for(let n=0;n0?this[0].getAttribute(n[e]):t[n[e]]="";return t}if(null==i)return this.length>0?this[0].getAttribute(n):"";for(let t=0;t0){if(1==this.length)return this[0].style[t];{let e=[];return this.each(function(n){let i=n.style[t];null==i&&(i=""),e.push(i)}),e}}}return this},each:function(t){for(let e=0;ethis.length-1?[]:t<0?-1*t>=this.length?[]:[this[this.length-1+t]]:[this[t]])},filter:function(e){let n=[];if(b(e,6))for(let i=0;i0&&this.each(function(e){t.indexOf(e)>=0&&n.indexOf(e)<0&&n.push(e)})}return x(n)},find:function(t){let e=[];return this.length>0&&this.each(function(n){const i=f(n,t);i.length>0&&i.forEach(function(t){e.indexOf(t)<0&&e.push(t)})}),x(e)},first:function(){let t=[];return this.length>0&&(t=[this[0]]),x(t)},get:function(t){return this[t||0]},has:function(t){let e=[];return this.length>0&&this.each(function(n){f(n,t).length>0&&e.indexOf(n)<0&&e.push(n)}),x(e)},hasClass:function(n){let i;b(n,5)?i=n:b(n,1)&&(i=n.split(" "));for(let e=0;e0&&i.every(function(t){return e.some(function(e){return t==e})}))return t}}return e},height:function(t){let e=p(t);if(b(e,1)){const t=parseFloat(e);if(isNaN(t))return this.each(function(t){t!=window&&t!=document&&(t.style.height=e)}),this;e=t}else if(null==e){if(this.length>0){const t=this[0];if(t==window)return window.innerHeight;if(t==document){const t=document.body,e=document.documentElement;return Math.max(t.offsetHeight,t.scrollHeight,e.clientHeight,e.offsetHeight,e.scrollHeight)}return t.clientHeight}}else 0==e?this.each(function(t){t.style.height=0}):this.each(function(t){t.style.height=e+"px"});return this},hide:function(){return this.each(function(t){t.style.display="none"}),this},hover:function(){const n=y([{t:1,o:t},{t:0,o:t},{t:6,o:e},{t:6,o:e}],arguments);let i=e;this.on("mouseenter",n[0],n[1],function(e){i||(n[2]&&n[2](e),i=t)});var s=this;this.on("mouseleave",n[0],n[1],function(l){let o=l,r=e;for(;null!=o;){if(s.filter(t=>t==o).length>0){r=t;break}o=o.parentNode}r||(i=e,n[3]&&n[3](l))})},html:function(t){let e=p(t);return null==e?this.length>0?this[0].innerHTML:"":(this.each(function(t){t.innerHTML=e}),this)},index:function(t){if(this.length>0){const e=t||this[0],n=e.parentNode;let i;if(n){if(i=n.children,[].indexOf)return[].indexOf.call(i,e);for(let t=0;t0){const t=this[0],e=getComputedStyle(t);let n=parseFloat(e.paddingTop),i=parseFloat(e.paddingBottom);return isNaN(n)&&(n=0),isNaN(i)&&(i=0),t.clientHeight-(n+i)}},innerWidth:function(t){if(null!=p(t))return this.width(t);if(this.length>0){const t=this[0],e=getComputedStyle(t);let n=parseFloat(e.paddingRight),i=parseFloat(e.paddingLeft);return isNaN(n)&&(n=0),isNaN(i)&&(i=0),t.clientWidth-(n+i)}},is:function(n){if(this.length>0){const e=this;let i=p(n);for(let n=0;n0&&(t=[this[this.length-1]]),x(t)},map:function(t){let e=[];for(let n=0;n0){const t=this[0].getBoundingClientRect();return{left:t.left+document.body.scrollLeft,top:t.top+document.body.scrollTop}}return{left:0,top:0}},offsetParent:function(){return this.length>0?this[0].offsetParent:null},on:function(){let n=y([{t:1,o:e},{t:1,o:t},{t:0,o:t},{t:6,o:e}],arguments);const i=n[0].replace(/\s/g,"").split(",");for(let s=0;s0?{left:this[0].offsetLeft,top:this[0].offsetTop}:{left:0,top:0}},prepend:function(t){let e=p(t);return g(e,this.append)||null==e?this:(v(e,this,function(t){t.insertAdjacentHTML("afterbegin",e)},function(t){t.insertBefore(e,t.firstChild)}),this)},prev:function(t){let e=[];return this.each(function(n){let i=n.previousSibling;if(t&&i){const s=f(n.parentNode,t);for(;null!=i;){if("#text"!=i.nodeName&&s.some(function(t){return t==i})){e.push(i);break}i=i.previousSibling}}else if(i)for(;null!=i;){if("#text"!=i.nodeName){e.push(i);break}i=i.previousSibling}}),x(e)},prop:function(n,i){const s=p(n);let l=p(i);if(b(s,5)){let t={};return s.forEach(function(e){t[e]=this.prop(e)}),t}const o=function(t,n){if(null!=l)"--"==l?this.each(function(e){e.removeAttribute(t)}):l==e?this.each(function(e){e.removeAttribute(t)}):this.attr(t,n);else if(this.length>0)return this[0].getAttribute(t)||""},r=function(n){if(null!=l)"--"==l?this.each(function(t){t.style.removeProperty(n)}):(l=0==l?e:t,this.each(function(t){t.style.setProperty(n,l)}));else if(this.length>0){let i=this[0],s=i[n];return null==s&&(s=null!=i.getAttribute(n)?t:e,i[n]=s),s}};let u="";switch(s){case"defaultChecked":u="checked";break;case"checked":if(!l&&this.length>0)return this[0].checked;break;case"defaultSelected":u="selected";break;case"selected":break;case"defaultDisabled":u="disabled";break;case"disabled":break;case"selectedIndex":null!=l&&l===parseInt(l,10)&&this.each(function(t){"SELECT"==t.nodeType&&(t.selectedIndex=l)});break;case"nodeName":return null!=i?void 0:this.length>0?this[0].nodeName:"";case"tagName":return null!=i?void 0:this.length>0?this[0].tagName:"";default:let t=r.call(this,s);if(null!=t&&void 0!==t)return t;if(null!=(t=o.call(this,s,l)))return t}if(""!=u){const t=o.call(this,u,u);if(null!=t)return t}else{const t=r.call(this,s);if(null!=t)return t}return this},push:function(t){return[].push.apply(this,t),this},ready:function(t){1==this.length&&this[0]==document&&("loading"!=document.readyState?t():document.addEventListener("DOMContentLoaded",t))},remove:function(t){return this.each(function(t){t.parentNode.removeChild(t)}),this.push([]),this},removeAttr:function(t){let e=p(t);return b(e,5)?e.forEach(function(t){this.each(function(e){e.removeAttribute(t)})}):"string"==typeof e&&this.each(function(t){t.removeAttribute(e)}),this},removeClass:function(t){let e=p(t);return"string"==typeof e&&(e=e.replace(/\,/g," ").replace(/\s\s/g," ")).indexOf(" ")>0&&(e=e.split(" ")),b(e,5)?this.each(function(t){e.forEach(function(e){t.className&&(t.className=t.className.split(" ").filter(function(t){return""!=t&&t!=e}).join(" "))})}):"string"==typeof e&&this.each(function(t){t.className&&(t.className=t.className.split(" ").filter(function(t){return""!=t&&t!=e}).join(" "))}),this},removeProp:function(t){return this.prop(t,"--"),this},serialize:function(){if(0==this.length)return"";let t=this[0];if(!t||"FORM"!==t.nodeName)return"";let e,n,i=[];for(e=t.elements.length-1;e>=0;e-=1)if(""!==t.elements[e].name)switch(t.elements[e].nodeName){case"INPUT":switch(t.elements[e].type){case"text":case"hidden":case"password":case"button":case"reset":case"submit":i.push(t.elements[e].name+"="+encodeURIComponent(t.elements[e].value));break;case"checkbox":case"radio":t.elements[e].checked&&i.push(t.elements[e].name+"="+encodeURIComponent(t.elements[e].value))}break;case"file":break;case"TEXTAREA":i.push(t.elements[e].name+"="+encodeURIComponent(t.elements[e].value));break;case"SELECT":switch(t.elements[e].type){case"select-one":i.push(t.elements[e].name+"="+encodeURIComponent(t.elements[e].value));break;case"select-multiple":for(n=t.elements[e].options.length-1;n>=0;n-=1)t.elements[e].options[n].selected&&i.push(t.elements[e].name+"="+encodeURIComponent(t.elements[e].options[n].value))}break;case"BUTTON":switch(t.elements[e].type){case"reset":case"submit":case"button":i.push(t.elements[e].name+"="+encodeURIComponent(t.elements[e].value))}}return i.join("&")},show:function(){return this.removeClass("hide"),this.each(function(t){t.style.display="block"}),this},siblings:function(t){let e=[],n=[],i=[];const s=p(t),l=function(t){e.some(function(e){return e==t})||e.push(t)},o=function(t,e){null!=e&&(i=f(t.parentNode,e)),n=t.parentNode.children;for(let s=0;s=0?i.splice(s,1):i.push(o)}n.className=i.join(" ")}else n.className=t})},val:function(t){return null==t?this.length>0?this[0].value:"":(this.each(function(e){e.value=t}),this)},width:function(t){let e=p(t);if(b(e,1)){const t=parseFloat(e);if(isNaN(t))return this.each(function(t){t!=window&&t!=document&&(t.style.width=e)}),this;e=t}else if(null==e){if(this.length>0){const t=this[0];if(t==window)return window.innerWidth;if(t==document){const t=document.body,e=document.documentElement;return Math.max(t.offsetWidth,t.scrollWidth,e.clientWidth,e.offsetWidth,e.scrollWidth)}return t.clientWidth}}else 0==e?this.each(function(t){t.style.width=0}):this.each(function(t){t.style.width=e+"px"});return this},wrap:function(t){return this},wrapAll:function(t){return this},wrapInner:function(t){return this}},window.$=function(t){return new h(t)},window.$.ajax=function(){let n=y([{t:1,o:t},{t:4,o:t}],arguments);n[1]=p(n[1]);var i=n[1]||{url:n[0]};i.url=n[0]||i.url,i.async=i.async||t,i.cache=i.cache||e,i.contentType=i.contentType||"application/x-www-form-urlencoded; charset=UTF-8",i.data=i.data||"",i.dataType=i.dataType||"",i.method=i.method||"GET",i.type=i.method||i.type;var s=new XMLHttpRequest;if(s.onload=function(){if(s.status>=200&&s.status<400){let t=s.responseText;"json"==i.dataType.toLowerCase()&&(t=JSON.parse(t)),i.success&&i.success(t,s.statusText,s),i.complete&&i.complete(t,s.statusText,s)}else i.error&&i.error(s,s.statusText);c=!1,N()},s.onerror=function(){i.error&&i.error(s,s.statusText),c=!1,N()},i.beforeSend&&i.beforeSend(s,i)==e)return e;u.unshift({req:s,opt:i}),N()},window.$.getJSON=function(t,e,n){$.ajax(t,{dataType:"json",complete:e,error:n})},window.$.extend=function(t){let n={},i=e,s=0;const l=arguments.length;"[object Boolean]"===Object.prototype.toString.call(arguments[0])&&(i=arguments[0],s++);const o=function(t){for(let e in t)Object.prototype.hasOwnProperty.call(t,e)&&(i&&"[object Object]"===Object.prototype.toString.call(t[e])?n[e]=window.$.extend(1,n[e],t[e]):n[e]=t[e])};for(;s 2 | 3 | 4 | 5 | 6 | selector.js 7 | 8 | 9 | 10 | 11 |
12 | Test #01 - Simple 13 |
14 | 17 | 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "selectorjs", 3 | "version": "0.9.12", 4 | "description": "A modern micro JS library that replaces the most common functionality of jQuery", 5 | "main": "gulpfile.js", 6 | "dependencies": { 7 | "gulp": "^4.0.0", 8 | "gulp-concat": "^2.6.1", 9 | "gulp-uglify": "^3.0.2", 10 | "uglify-es": "^3.3.9" 11 | }, 12 | "devDependencies": {}, 13 | "scripts": { 14 | "test": "gulp selector" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "http://www.github.com/websilk/selector" 19 | }, 20 | "keywords": [ 21 | "jquery", 22 | "replacement", 23 | "microjs", 24 | "micro", 25 | "library", 26 | "micro", 27 | "framework" 28 | ], 29 | "author": "Mark Entingh", 30 | "license": "MIT" 31 | } 32 | -------------------------------------------------------------------------------- /tests/01-simple/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | selector.js 7 | 8 | 9 | 10 | 11 |
12 |

13 | Selector.js 14 |

15 |

16 | A micro javascript library used as a replacement for jQuery, weighing in at nearly 5KB.
Below are a set of tests 17 | that will work in both jQuery and selector.js. 18 |

19 |
20 |
21 |
22 |
23 | Hello World 24 |
25 |
26 | Stylize 27 |
28 |
29 |
30 | 31 |
32 | 33 |
34 |
35 |
mimic things here...
36 |
37 |
38 |
39 |
40 | Teleport 41 |
42 |
...beam me up, Scotty.
43 |
44 |
45 |
46 |
47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /tests/01-simple/style.css: -------------------------------------------------------------------------------- 1 | *{box-sizing:border-box;} 2 | body{font-family:Arial, Helvetica, sans-serif;} 3 | .header{height:108px;} 4 | .button{color:#fff; background:#56bf94; padding:7px 15px; border-radius:4px;box-shadow:3px 3px 0px rgba(0,0,0,0.15);} 5 | .button:link{text-decoration:none;} 6 | .button:hover{background:#1bcd84;} 7 | .row{width:100%; box-sizing:border-box;} 8 | .row:after{visibility:hidden; display:block; font-size:0; content:" "; clear:both; height:0;} 9 | .col{float:left; position:relative; display:inline-block;} 10 | .pad{padding:15px;} 11 | .pad-lg{padding:30px;} 12 | .pad-width-lg{padding-left:30px; padding-right:30px;} 13 | .pad-height{padding-top:15px; padding-bottom:15px;} 14 | .result{background-color:#b3d9ff;} 15 | .teleport{background-color:#ffcce0; color:#e600ac;} 16 | .teleport .button{background-color:#e600ac;} 17 | .teleport .button:hover{background-color:#ff3399;} 18 | /* input placeholder text color */ 19 | input[type=text]{padding:8px 15px; font-size:17px; width:90%;} 20 | input[type=text]::-webkit-input-placeholder { /* Chrome/Opera/Safari */ color: #ccc;} 21 | input[type=text]::-moz-placeholder { /* Firefox 19+ */ color: #ccc;} 22 | input[type=text]:-ms-input-placeholder { /* IE 10+ */ color: #ccc;} 23 | input[type=text]:-moz-placeholder { /* Firefox 18- */ color: #ccc;} -------------------------------------------------------------------------------- /tests/01-simple/test.js: -------------------------------------------------------------------------------- 1 | // selector.js (under 5 KB minified gzipped) 2 | // developed by Mark Entingh (www.markentingh.com) 3 | // looks like jQuery, acts like jQuery, but isn't jQuery. 4 | 5 | (function(){ 6 | var hello = 0; 7 | var style = 0; 8 | 9 | $('.hello-world').on('click', function(e){ 10 | hello = hello >= 5 ? 0 : hello + 1; 11 | switch(hello){ 12 | case 0: $(this).html('Hello World'); break; 13 | case 1: $(this).html('That tickles...'); break; 14 | case 2: $(this).html('No more, please.'); break; 15 | case 3: $(this).html('This is torture!'); break; 16 | case 4: $(this).html('Okay, now I\'m angry.'); break; 17 | case 5: $(this).html('Goodbye.'); break; 18 | } 19 | }); 20 | 21 | $('.change-style').on('click', function(e){ 22 | style = style >= 5 ? 0 : style + 1; 23 | switch(style){ 24 | case 0: 25 | $(this).css({'font-size':24, backgroundColor:'#0066ff', border:'2px solid #0033cc'}); 26 | break; 27 | case 1: 28 | $(this).css({'font-size':10, backgroundColor:'#ace600', border:'1px solid #86b300'}); 29 | break; 30 | case 2: 31 | $(this).css({'font-size':17, backgroundColor:'#ff9900', border:'3px solid #ff6600'}); 32 | break; 33 | case 3: 34 | $(this).css({'font-size':40, backgroundColor:'#0099e6', border:'8px solid #0066cc'}); 35 | break; 36 | case 4: 37 | $(this).css({'font-size':28, backgroundColor:'#ff6666', border:'4px solid #ff3333'}); 38 | break; 39 | case 5: 40 | $(this).css({'font-size':14, backgroundColor:'#ffcc00', border:'2px solid #ffa64d'}); 41 | break; 42 | } 43 | 44 | }); 45 | 46 | $('#texter').on('keyup', function(e){ 47 | $('.result').html($(this).val()); 48 | }); 49 | 50 | $('.teleport a').on('click', function(){ 51 | var speed = 2000; 52 | if($(this).parents('.teleport').find('.hello-world').length > 0){ 53 | //teleport back to original spot 54 | $('.teleport .buttons').animate({opacity:0}, speed); 55 | setTimeout(function(){ 56 | $('.header').append($('.buttons')); 57 | $('.buttons, .beam').animate({opacity:1}, speed); 58 | $('.beam').show(); 59 | }, speed); 60 | }else{ 61 | $('.buttons, .beam').animate({opacity:0}, speed); 62 | setTimeout(function(){ 63 | $('.beam').hide(); 64 | $('.teleport .platform').append($('.buttons')); 65 | $('.buttons').animate({opacity:1}, speed); 66 | }, speed); 67 | } 68 | 69 | 70 | }); 71 | })(); -------------------------------------------------------------------------------- /tests/01-simple/velocity.js: -------------------------------------------------------------------------------- 1 | /*! VelocityJS.org (1.5.0). (C) 2014 Julian Shapiro. MIT @license: en.wikipedia.org/wiki/MIT_License */ 2 | /*! VelocityJS.org jQuery Shim (1.0.1). (C) 2014 The jQuery Foundation. MIT @license: en.wikipedia.org/wiki/MIT_License. */ 3 | !function(a){"use strict";function b(a){var b=a.length,d=c.type(a);return"function"!==d&&!c.isWindow(a)&&(!(1!==a.nodeType||!b)||("array"===d||0===b||"number"==typeof b&&b>0&&b-1 in a))}if(!a.jQuery){var c=function(a,b){return new c.fn.init(a,b)};c.isWindow=function(a){return a&&a===a.window},c.type=function(a){return a?"object"==typeof a||"function"==typeof a?e[g.call(a)]||"object":typeof a:a+""},c.isArray=Array.isArray||function(a){return"array"===c.type(a)},c.isPlainObject=function(a){var b;if(!a||"object"!==c.type(a)||a.nodeType||c.isWindow(a))return!1;try{if(a.constructor&&!f.call(a,"constructor")&&!f.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(d){return!1}for(b in a);return b===undefined||f.call(a,b)},c.each=function(a,c,d){var e=0,f=a.length,g=b(a);if(d){if(g)for(;e0?e=g:c=g}while(Math.abs(f)>r&&++h=q?k(b,h):0===i?h:m(b,c,c+u)}function o(){y=!0,a===c&&d===e||l()}var p=4,q=.001,r=1e-7,s=10,t=11,u=1/(t-1),v="Float32Array"in b;if(4!==arguments.length)return!1;for(var w=0;w<4;++w)if("number"!=typeof arguments[w]||isNaN(arguments[w])||!isFinite(arguments[w]))return!1;a=Math.min(a,1),d=Math.min(d,1),a=Math.max(a,0),d=Math.max(d,0);var x=v?new Float32Array(t):new Array(t),y=!1,z=function(b){return y||o(),a===c&&d===e?b:0===b?0:1===b?1:i(n(b),c,e)};z.getControlPoints=function(){return[{x:a,y:c},{x:d,y:e}]};var A="generateBezier("+[a,c,d,e]+")";return z.toString=function(){return A},z}function l(a,b){var c=a;return u.isString(a)?y.Easings[a]||(c=!1):c=u.isArray(a)&&1===a.length?j.apply(null,a):u.isArray(a)&&2===a.length?z.apply(null,a.concat([b])):!(!u.isArray(a)||4!==a.length)&&k.apply(null,a),c===!1&&(c=y.Easings[y.defaults.easing]?y.defaults.easing:x),c}function m(a){if(a){var b=y.timestamp&&a!==!0?a:r.now(),c=y.State.calls.length;c>1e4&&(y.State.calls=e(y.State.calls),c=y.State.calls.length);for(var f=0;f4;a--){var b=c.createElement("div");if(b.innerHTML="",b.getElementsByTagName("span").length)return b=null,a}return d}(),q=function(){var a=0;return b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame||function(b){var c,d=(new Date).getTime();return c=Math.max(0,16-(d-a)),a=d+c,setTimeout(function(){b(d+c)},c)}}(),r=function(){var a=b.performance||{};if("function"!=typeof a.now){var c=a.timing&&a.timing.navigationStart?a.timing.navigationStart:(new Date).getTime();a.now=function(){return(new Date).getTime()-c}}return a}(),s=function(){var a=Array.prototype.slice;try{return a.call(c.documentElement),a}catch(b){return function(b,c){var d=this.length;if("number"!=typeof b&&(b=0),"number"!=typeof c&&(c=d),this.slice)return a.call(this,b,c);var e,f=[],g=b>=0?b:Math.max(0,d+b),h=c<0?d+c:Math.min(c,d),i=h-g;if(i>0)if(f=new Array(i),this.charAt)for(e=0;e=0}:function(a,b){for(var c=0;c1e-4&&Math.abs(h.v)>1e-4))break;return f?function(a){return j[a*(j.length-1)|0]}:k}}();y.Easings={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},spring:function(a){return 1-Math.cos(4.5*a*Math.PI)*Math.exp(6*-a)}},o.each([["ease",[.25,.1,.25,1]],["ease-in",[.42,0,1,1]],["ease-out",[0,0,.58,1]],["ease-in-out",[.42,0,.58,1]],["easeInSine",[.47,0,.745,.715]],["easeOutSine",[.39,.575,.565,1]],["easeInOutSine",[.445,.05,.55,.95]],["easeInQuad",[.55,.085,.68,.53]],["easeOutQuad",[.25,.46,.45,.94]],["easeInOutQuad",[.455,.03,.515,.955]],["easeInCubic",[.55,.055,.675,.19]],["easeOutCubic",[.215,.61,.355,1]],["easeInOutCubic",[.645,.045,.355,1]],["easeInQuart",[.895,.03,.685,.22]],["easeOutQuart",[.165,.84,.44,1]],["easeInOutQuart",[.77,0,.175,1]],["easeInQuint",[.755,.05,.855,.06]],["easeOutQuint",[.23,1,.32,1]],["easeInOutQuint",[.86,0,.07,1]],["easeInExpo",[.95,.05,.795,.035]],["easeOutExpo",[.19,1,.22,1]],["easeInOutExpo",[1,0,0,1]],["easeInCirc",[.6,.04,.98,.335]],["easeOutCirc",[.075,.82,.165,1]],["easeInOutCirc",[.785,.135,.15,.86]]],function(a,b){y.Easings[b[0]]=k.apply(null,b[1])});var A=y.CSS={RegEx:{isHex:/^#([A-f\d]{3}){1,2}$/i,valueUnwrap:/^[A-z]+\((.*)\)$/i,wrappedValueAlreadyExtracted:/[0-9.]+ [0-9.]+ [0-9.]+( [0-9.]+)?/,valueSplit:/([A-z]+\(.+\))|(([A-z0-9#-.]+?)(?=\s|$))/gi},Lists:{colors:["fill","stroke","stopColor","color","backgroundColor","borderColor","borderTopColor","borderRightColor","borderBottomColor","borderLeftColor","outlineColor"],transformsBase:["translateX","translateY","scale","scaleX","scaleY","skewX","skewY","rotateZ"],transforms3D:["transformPerspective","translateZ","scaleZ","rotateX","rotateY"],units:["%","em","ex","ch","rem","vw","vh","vmin","vmax","cm","mm","Q","in","pc","pt","px","deg","grad","rad","turn","s","ms"],colorNames:{aliceblue:"240,248,255",antiquewhite:"250,235,215",aquamarine:"127,255,212",aqua:"0,255,255",azure:"240,255,255",beige:"245,245,220",bisque:"255,228,196",black:"0,0,0",blanchedalmond:"255,235,205",blueviolet:"138,43,226",blue:"0,0,255",brown:"165,42,42",burlywood:"222,184,135",cadetblue:"95,158,160",chartreuse:"127,255,0",chocolate:"210,105,30",coral:"255,127,80",cornflowerblue:"100,149,237",cornsilk:"255,248,220",crimson:"220,20,60",cyan:"0,255,255",darkblue:"0,0,139",darkcyan:"0,139,139",darkgoldenrod:"184,134,11",darkgray:"169,169,169",darkgrey:"169,169,169",darkgreen:"0,100,0",darkkhaki:"189,183,107",darkmagenta:"139,0,139",darkolivegreen:"85,107,47",darkorange:"255,140,0",darkorchid:"153,50,204",darkred:"139,0,0",darksalmon:"233,150,122",darkseagreen:"143,188,143",darkslateblue:"72,61,139",darkslategray:"47,79,79",darkturquoise:"0,206,209",darkviolet:"148,0,211",deeppink:"255,20,147",deepskyblue:"0,191,255",dimgray:"105,105,105",dimgrey:"105,105,105",dodgerblue:"30,144,255",firebrick:"178,34,34",floralwhite:"255,250,240",forestgreen:"34,139,34",fuchsia:"255,0,255",gainsboro:"220,220,220",ghostwhite:"248,248,255",gold:"255,215,0",goldenrod:"218,165,32",gray:"128,128,128",grey:"128,128,128",greenyellow:"173,255,47",green:"0,128,0",honeydew:"240,255,240",hotpink:"255,105,180",indianred:"205,92,92",indigo:"75,0,130",ivory:"255,255,240",khaki:"240,230,140",lavenderblush:"255,240,245",lavender:"230,230,250",lawngreen:"124,252,0",lemonchiffon:"255,250,205",lightblue:"173,216,230",lightcoral:"240,128,128",lightcyan:"224,255,255",lightgoldenrodyellow:"250,250,210",lightgray:"211,211,211",lightgrey:"211,211,211",lightgreen:"144,238,144",lightpink:"255,182,193",lightsalmon:"255,160,122",lightseagreen:"32,178,170",lightskyblue:"135,206,250",lightslategray:"119,136,153",lightsteelblue:"176,196,222",lightyellow:"255,255,224",limegreen:"50,205,50",lime:"0,255,0",linen:"250,240,230",magenta:"255,0,255",maroon:"128,0,0",mediumaquamarine:"102,205,170",mediumblue:"0,0,205",mediumorchid:"186,85,211",mediumpurple:"147,112,219",mediumseagreen:"60,179,113",mediumslateblue:"123,104,238",mediumspringgreen:"0,250,154",mediumturquoise:"72,209,204",mediumvioletred:"199,21,133",midnightblue:"25,25,112",mintcream:"245,255,250",mistyrose:"255,228,225",moccasin:"255,228,181",navajowhite:"255,222,173",navy:"0,0,128",oldlace:"253,245,230",olivedrab:"107,142,35",olive:"128,128,0",orangered:"255,69,0",orange:"255,165,0",orchid:"218,112,214",palegoldenrod:"238,232,170",palegreen:"152,251,152",paleturquoise:"175,238,238",palevioletred:"219,112,147",papayawhip:"255,239,213",peachpuff:"255,218,185",peru:"205,133,63",pink:"255,192,203",plum:"221,160,221",powderblue:"176,224,230",purple:"128,0,128",red:"255,0,0",rosybrown:"188,143,143",royalblue:"65,105,225",saddlebrown:"139,69,19",salmon:"250,128,114",sandybrown:"244,164,96",seagreen:"46,139,87",seashell:"255,245,238",sienna:"160,82,45",silver:"192,192,192",skyblue:"135,206,235",slateblue:"106,90,205",slategray:"112,128,144",snow:"255,250,250",springgreen:"0,255,127",steelblue:"70,130,180",tan:"210,180,140",teal:"0,128,128",thistle:"216,191,216",tomato:"255,99,71",turquoise:"64,224,208",violet:"238,130,238",wheat:"245,222,179",whitesmoke:"245,245,245",white:"255,255,255",yellowgreen:"154,205,50",yellow:"255,255,0"}},Hooks:{templates:{textShadow:["Color X Y Blur","black 0px 0px 0px"],boxShadow:["Color X Y Blur Spread","black 0px 0px 0px 0px"],clip:["Top Right Bottom Left","0px 0px 0px 0px"],backgroundPosition:["X Y","0% 0%"],transformOrigin:["X Y Z","50% 50% 0px"],perspectiveOrigin:["X Y","50% 50%"]},registered:{},register:function(){for(var a=0;a=1?"":"alpha(opacity="+parseInt(100*parseFloat(c),10)+")"}else switch(a){case"name":return"opacity";case"extract":return c;case"inject":return c}}},register:function(){function a(a,b,c){if("border-box"===A.getPropertyValue(b,"boxSizing").toString().toLowerCase()===(c||!1)){var d,e,f=0,g="width"===a?["Left","Right"]:["Top","Bottom"],h=["padding"+g[0],"padding"+g[1],"border"+g[0]+"Width","border"+g[1]+"Width"];for(d=0;d9)||y.State.isGingerbread||(A.Lists.transformsBase=A.Lists.transformsBase.concat(A.Lists.transforms3D));for(var c=0;c8)&&3===f.split(" ").length&&(f+=" 1"),f;case"inject":return/^rgb/.test(e)?e:(p<=8?4===e.split(" ").length&&(e=e.split(/\s+/).slice(0,3).join(" ")):3===e.split(" ").length&&(e+=" 1"),(p<=8?"rgb":"rgba")+"("+e.replace(/\s+/g,",").replace(/\.(\d)+(?=,)/g,"")+")")}}}();A.Normalizations.registered.innerWidth=b("width",!0),A.Normalizations.registered.innerHeight=b("height",!0),A.Normalizations.registered.outerWidth=b("width"),A.Normalizations.registered.outerHeight=b("height")}},Names:{camelCase:function(a){return a.replace(/-(\w)/g,function(a,b){return b.toUpperCase()})},SVGAttribute:function(a){var b="width|height|x|y|cx|cy|r|rx|ry|x1|x2|y1|y2";return(p||y.State.isAndroid&&!y.State.isChrome)&&(b+="|transform"),new RegExp("^("+b+")$","i").test(a)},prefixCheck:function(a){if(y.State.prefixMatches[a])return[y.State.prefixMatches[a],!0];for(var b=["","Webkit","Moz","ms","O"],c=0,d=b.length;c=2&&console.log("Get "+c+": "+i),i},setPropertyValue:function(a,c,d,e,f){var h=c;if("scroll"===c)f.container?f.container["scroll"+f.direction]=d:"Left"===f.direction?b.scrollTo(d,f.alternateValue):b.scrollTo(f.alternateValue,d);else if(A.Normalizations.registered[c]&&"transform"===A.Normalizations.registered[c]("name",a))A.Normalizations.registered[c]("inject",a,d),h="transform",d=g(a).transformCache[c];else{if(A.Hooks.registered[c]){var i=c,j=A.Hooks.getRoot(c);e=e||A.getPropertyValue(a,j),d=A.Hooks.injectValue(i,d,e),c=j}if(A.Normalizations.registered[c]&&(d=A.Normalizations.registered[c]("inject",a,d),c=A.Normalizations.registered[c]("name",a)),h=A.Names.prefixCheck(c)[0],p<=8)try{a.style[h]=d}catch(l){y.debug&&console.log("Browser does not support ["+d+"] for ["+h+"]")}else{var k=g(a);k&&k.isSVG&&A.Names.SVGAttribute(c)?a.setAttribute(c,d):a.style[h]=d}y.debug>=2&&console.log("Set "+c+" ("+h+"): "+d)}return[h,d]},flushTransformCache:function(a){var b="",c=g(a);if((p||y.State.isAndroid&&!y.State.isChrome)&&c&&c.isSVG){var d=function(b){return parseFloat(A.getPropertyValue(a,b))},e={translate:[d("translateX"),d("translateY")],skewX:[d("skewX")],skewY:[d("skewY")],scale:1!==d("scale")?[d("scale"),d("scale")]:[d("scaleX"),d("scaleY")],rotate:[d("rotateZ"),0,0]};o.each(g(a).transformCache,function(a){/^translate/i.test(a)?a="translate":/^scale/i.test(a)?a="scale":/^rotate/i.test(a)&&(a="rotate"),e[a]&&(b+=a+"("+e[a].join(" ")+") ",delete e[a])})}else{var f,h;o.each(g(a).transformCache,function(c){if(f=g(a).transformCache[c],"transformPerspective"===c)return h=f,!0;9===p&&"rotateZ"===c&&(c="rotate"),b+=c+f+" "}),h&&(b="perspective"+h+" "+b)}A.setPropertyValue(a,"transform",b)}};A.Hooks.register(),A.Normalizations.register(),y.hook=function(a,b,c){var e;return a=f(a),o.each(a,function(a,f){if(g(f)===d&&y.init(f),c===d)e===d&&(e=A.getPropertyValue(f,b));else{var h=A.setPropertyValue(f,b,c);"transform"===h[0]&&y.CSS.flushTransformCache(f),e=h}}),e};var B=function(){function a(){return k?z.promise||null:p}function e(a,e){function f(f){var k,n;if(i.begin&&0===D)try{i.begin.call(r,r)}catch(V){setTimeout(function(){throw V},1)}if("scroll"===G){var p,q,w,x=/^x$/i.test(i.axis)?"Left":"Top",B=parseFloat(i.offset)||0;i.container?u.isWrapped(i.container)||u.isNode(i.container)?(i.container=i.container[0]||i.container,p=i.container["scroll"+x],w=p+o(a).position()[x.toLowerCase()]+B):i.container=null:(p=y.State.scrollAnchor[y.State["scrollProperty"+x]],q=y.State.scrollAnchor[y.State["scrollProperty"+("Left"===x?"Top":"Left")]],w=o(a).offset()[x.toLowerCase()]+B),j={scroll:{rootPropertyValue:!1,startValue:p,currentValue:p,endValue:w,unitType:"",easing:i.easing,scrollData:{container:i.container,direction:x,alternateValue:q}},element:a},y.debug&&console.log("tweensContainer (scroll): ",j.scroll,a)}else if("reverse"===G){if(!(k=g(a)))return;if(!k.tweensContainer)return void o.dequeue(a,i.queue);"none"===k.opts.display&&(k.opts.display="auto"),"hidden"===k.opts.visibility&&(k.opts.visibility="visible"),k.opts.loop=!1,k.opts.begin=null,k.opts.complete=null,v.easing||delete i.easing,v.duration||delete i.duration,i=o.extend({},k.opts,i),n=o.extend(!0,{},k?k.tweensContainer:null);for(var E in n)if(n.hasOwnProperty(E)&&"element"!==E){var F=n[E].startValue;n[E].startValue=n[E].currentValue=n[E].endValue,n[E].endValue=F,u.isEmptyObject(v)||(n[E].easing=i.easing),y.debug&&console.log("reverse tweensContainer ("+E+"): "+JSON.stringify(n[E]),a)}j=n}else if("start"===G){k=g(a),k&&k.tweensContainer&&k.isAnimating===!0&&(n=k.tweensContainer);var H=function(e,f){var g,l=A.Hooks.getRoot(e),m=!1,p=f[0],q=f[1],r=f[2] 4 | ;if(!(k&&k.isSVG||"tween"===l||A.Names.prefixCheck(l)[1]!==!1||A.Normalizations.registered[l]!==d))return void(y.debug&&console.log("Skipping ["+l+"] due to a lack of browser support."));(i.display!==d&&null!==i.display&&"none"!==i.display||i.visibility!==d&&"hidden"!==i.visibility)&&/opacity|filter/.test(e)&&!r&&0!==p&&(r=0),i._cacheValues&&n&&n[e]?(r===d&&(r=n[e].endValue+n[e].unitType),m=k.rootPropertyValueCache[l]):A.Hooks.registered[e]?r===d?(m=A.getPropertyValue(a,l),r=A.getPropertyValue(a,e,m)):m=A.Hooks.templates[l][1]:r===d&&(r=A.getPropertyValue(a,e));var s,t,v,w=!1,x=function(a,b){var c,d;return d=(b||"0").toString().toLowerCase().replace(/[%A-z]+$/,function(a){return c=a,""}),c||(c=A.Values.getUnitType(a)),[d,c]};if(r!==p&&u.isString(r)&&u.isString(p)){g="";var z=0,B=0,C=[],D=[],E=0,F=0,G=0;for(r=A.Hooks.fixColors(r),p=A.Hooks.fixColors(p);z=4&&"("===H?E++:(E&&E<5||E>=4&&")"===H&&--E<5)&&(E=0),0===F&&"r"===H||1===F&&"g"===H||2===F&&"b"===H||3===F&&"a"===H||F>=3&&"("===H?(3===F&&"a"===H&&(G=1),F++):G&&","===H?++G>3&&(F=G=0):(G&&F<(G?5:4)||F>=(G?4:3)&&")"===H&&--F<(G?5:4))&&(F=G=0)}}z===r.length&&B===p.length||(y.debug&&console.error('Trying to pattern match mis-matched strings ["'+p+'", "'+r+'"]'),g=d),g&&(C.length?(y.debug&&console.log('Pattern found "'+g+'" -> ',C,D,"["+r+","+p+"]"),r=C,p=D,t=v=""):g=d)}g||(s=x(e,r),r=s[0],v=s[1],s=x(e,p),p=s[0].replace(/^([+-\/*])=/,function(a,b){return w=b,""}),t=s[1],r=parseFloat(r)||0,p=parseFloat(p)||0,"%"===t&&(/^(fontSize|lineHeight)$/.test(e)?(p/=100,t="em"):/^scale/.test(e)?(p/=100,t=""):/(Red|Green|Blue)$/i.test(e)&&(p=p/100*255,t="")));if(/[\/*]/.test(w))t=v;else if(v!==t&&0!==r)if(0===p)t=v;else{h=h||function(){var d={myParent:a.parentNode||c.body,position:A.getPropertyValue(a,"position"),fontSize:A.getPropertyValue(a,"fontSize")},e=d.position===M.lastPosition&&d.myParent===M.lastParent,f=d.fontSize===M.lastFontSize;M.lastParent=d.myParent,M.lastPosition=d.position,M.lastFontSize=d.fontSize;var g={};if(f&&e)g.emToPx=M.lastEmToPx,g.percentToPxWidth=M.lastPercentToPxWidth,g.percentToPxHeight=M.lastPercentToPxHeight;else{var h=k&&k.isSVG?c.createElementNS("http://www.w3.org/2000/svg","rect"):c.createElement("div");y.init(h),d.myParent.appendChild(h),o.each(["overflow","overflowX","overflowY"],function(a,b){y.CSS.setPropertyValue(h,b,"hidden")}),y.CSS.setPropertyValue(h,"position",d.position),y.CSS.setPropertyValue(h,"fontSize",d.fontSize),y.CSS.setPropertyValue(h,"boxSizing","content-box"),o.each(["minWidth","maxWidth","width","minHeight","maxHeight","height"],function(a,b){y.CSS.setPropertyValue(h,b,"100%")}),y.CSS.setPropertyValue(h,"paddingLeft","100em"),g.percentToPxWidth=M.lastPercentToPxWidth=(parseFloat(A.getPropertyValue(h,"width",null,!0))||1)/100,g.percentToPxHeight=M.lastPercentToPxHeight=(parseFloat(A.getPropertyValue(h,"height",null,!0))||1)/100,g.emToPx=M.lastEmToPx=(parseFloat(A.getPropertyValue(h,"paddingLeft"))||1)/100,d.myParent.removeChild(h)}return null===M.remToPx&&(M.remToPx=parseFloat(A.getPropertyValue(c.body,"fontSize"))||16),null===M.vwToPx&&(M.vwToPx=parseFloat(b.innerWidth)/100,M.vhToPx=parseFloat(b.innerHeight)/100),g.remToPx=M.remToPx,g.vwToPx=M.vwToPx,g.vhToPx=M.vhToPx,y.debug>=1&&console.log("Unit ratios: "+JSON.stringify(g),a),g}();var S=/margin|padding|left|right|width|text|word|letter/i.test(e)||/X$/.test(e)||"x"===e?"x":"y";switch(v){case"%":r*="x"===S?h.percentToPxWidth:h.percentToPxHeight;break;case"px":break;default:r*=h[v+"ToPx"]}switch(t){case"%":r*=1/("x"===S?h.percentToPxWidth:h.percentToPxHeight);break;case"px":break;default:r*=1/h[t+"ToPx"]}}switch(w){case"+":p=r+p;break;case"-":p=r-p;break;case"*":p*=r;break;case"/":p=r/p}j[e]={rootPropertyValue:m,startValue:r,currentValue:r,endValue:p,unitType:t,easing:q},g&&(j[e].pattern=g),y.debug&&console.log("tweensContainer ("+e+"): "+JSON.stringify(j[e]),a)};for(var I in s)if(s.hasOwnProperty(I)){var J=A.Names.camelCase(I),K=function(b,c){var d,f,g;return u.isFunction(b)&&(b=b.call(a,e,C)),u.isArray(b)?(d=b[0],!u.isArray(b[1])&&/^[\d-]/.test(b[1])||u.isFunction(b[1])||A.RegEx.isHex.test(b[1])?g=b[1]:u.isString(b[1])&&!A.RegEx.isHex.test(b[1])&&y.Easings[b[1]]||u.isArray(b[1])?(f=c?b[1]:l(b[1],i.duration),g=b[2]):g=b[1]||b[2]):d=b,c||(f=f||i.easing),u.isFunction(d)&&(d=d.call(a,e,C)),u.isFunction(g)&&(g=g.call(a,e,C)),[d||0,f,g]}(s[I]);if(t(A.Lists.colors,J)){var L=K[0],O=K[1],P=K[2];if(A.RegEx.isHex.test(L)){for(var Q=["Red","Green","Blue"],R=A.Values.hexToRgb(L),S=P?A.Values.hexToRgb(P):d,T=0;T 2 | 3 | 4 | 5 | 6 | jquery-3.2.0.min.js 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tests/02-over-9000/iframe_selector.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | selector.js 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tests/02-over-9000/iframe_zepto.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | zepto-1.2.0.min.js 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tests/02-over-9000/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | selector.js 7 | 8 | 9 | 10 | 11 |
12 |

Over 9,000!?!?

13 |

This test only works if running on a local / remote server. 14 | Do not load this html file into your web browser or you will get a cross-origin error! 15 |

16 | 17 |
18 |
19 | 25 |
26 |
27 | 32 |
33 |
34 | Run Test 35 |
36 |
37 |
38 |
39 |

jQuery results

40 |
41 |
42 |
43 |

Zepto results

44 |
45 |
46 |
47 |

Selector.js results

48 |
49 |
50 |
51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /tests/02-over-9000/runtest.js: -------------------------------------------------------------------------------- 1 | function runTest(){ 2 | var start = new Date(); 3 | console.log('running test...'); 4 | var index = 0; 5 | for(var x = 0; x <= 10000; x++){ 6 | //append 10,000 blocks of HTML (30,000 DOM elements) 7 | index++; 8 | if(index > 5){index = 1;} 9 | $('body').append('
'); 10 | } 11 | 12 | //destroy test 13 | $('.row').remove(); 14 | 15 | return {time: (new Date()) - start}; 16 | } -------------------------------------------------------------------------------- /tests/02-over-9000/style.css: -------------------------------------------------------------------------------- 1 | *{box-sizing:border-box;} 2 | body{font-family:Arial, Helvetica, sans-serif;} 3 | .header{height:108px;} 4 | .button{color:#fff; background:#56bf94; padding:7px 15px; border-radius:4px;box-shadow:3px 3px 0px rgba(0,0,0,0.15);} 5 | .button:link{text-decoration:none;} 6 | .button:hover{background:#1bcd84;} 7 | .row{display:block; width:100%; box-sizing:border-box;} 8 | .row:after{visibility:hidden; display:block; font-size:0; content:" "; clear:both; height:0;} 9 | .col{float:left; position:relative; display:inline-block;} 10 | .pad{padding:15px;} 11 | .pad-sm{padding:5px;} 12 | .pad-lg{padding:30px;} 13 | .pad-right{padding-right:15px;} 14 | .pad-width-lg{padding-left:30px; padding-right:30px;} 15 | .pad-height{padding-top:15px; padding-bottom:15px;} 16 | iframe{width:0px; height:0px; border:0 none;} -------------------------------------------------------------------------------- /tests/02-over-9000/test.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 3 | var button = document.getElementsByClassName('button')[0]; 4 | var select = document.getElementById('select_framework'); 5 | var times = document.getElementById('select_times'); 6 | var counter = 0; 7 | 8 | function runTest(id){ 9 | var results = document.getElementsByClassName('results_' + id)[0].getElementsByClassName('content')[0]; 10 | results.innerHTML += print('running...', 'running'); 11 | var r = document.getElementById('iframe_' + id).contentWindow.runTest(); 12 | document.getElementById('running').remove(); 13 | results.innerHTML += print(r.time + ' ms'); 14 | } 15 | 16 | function print(str, id){ 17 | return '
' + str + '
' 18 | } 19 | button.onclick = function(){ 20 | counter = 0; 21 | button.style.display = 'none'; 22 | var len = parseInt(times.value); 23 | setTimeout(function(){ 24 | run(); 25 | },1); 26 | 27 | function run(){ 28 | if(select.value == 'all'){ 29 | runTest('jquery'); 30 | runTest('zepto'); 31 | runTest('selector'); 32 | }else{ 33 | runTest(select.value); 34 | } 35 | counter++ 36 | if(counter < len){ 37 | setTimeout(function(){ 38 | run(); 39 | },1); 40 | }else{ 41 | button.style.display = 'block'; 42 | } 43 | } 44 | } 45 | })(); -------------------------------------------------------------------------------- /tests/02-over-9000/zepto-1.2.0.min.js: -------------------------------------------------------------------------------- 1 | /* Zepto v1.2.0 - zepto event ajax form ie - zeptojs.com/license */ 2 | !function(t,e){"function"==typeof define&&define.amd?define(function(){return e(t)}):e(t)}(this,function(t){var e=function(){function $(t){return null==t?String(t):S[C.call(t)]||"object"}function F(t){return"function"==$(t)}function k(t){return null!=t&&t==t.window}function M(t){return null!=t&&t.nodeType==t.DOCUMENT_NODE}function R(t){return"object"==$(t)}function Z(t){return R(t)&&!k(t)&&Object.getPrototypeOf(t)==Object.prototype}function z(t){var e=!!t&&"length"in t&&t.length,n=r.type(t);return"function"!=n&&!k(t)&&("array"==n||0===e||"number"==typeof e&&e>0&&e-1 in t)}function q(t){return a.call(t,function(t){return null!=t})}function H(t){return t.length>0?r.fn.concat.apply([],t):t}function I(t){return t.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function V(t){return t in l?l[t]:l[t]=new RegExp("(^|\\s)"+t+"(\\s|$)")}function _(t,e){return"number"!=typeof e||h[I(t)]?e:e+"px"}function B(t){var e,n;return c[t]||(e=f.createElement(t),f.body.appendChild(e),n=getComputedStyle(e,"").getPropertyValue("display"),e.parentNode.removeChild(e),"none"==n&&(n="block"),c[t]=n),c[t]}function U(t){return"children"in t?u.call(t.children):r.map(t.childNodes,function(t){return 1==t.nodeType?t:void 0})}function X(t,e){var n,r=t?t.length:0;for(n=0;r>n;n++)this[n]=t[n];this.length=r,this.selector=e||""}function J(t,r,i){for(n in r)i&&(Z(r[n])||L(r[n]))?(Z(r[n])&&!Z(t[n])&&(t[n]={}),L(r[n])&&!L(t[n])&&(t[n]=[]),J(t[n],r[n],i)):r[n]!==e&&(t[n]=r[n])}function W(t,e){return null==e?r(t):r(t).filter(e)}function Y(t,e,n,r){return F(e)?e.call(t,n,r):e}function G(t,e,n){null==n?t.removeAttribute(e):t.setAttribute(e,n)}function K(t,n){var r=t.className||"",i=r&&r.baseVal!==e;return n===e?i?r.baseVal:r:void(i?r.baseVal=n:t.className=n)}function Q(t){try{return t?"true"==t||("false"==t?!1:"null"==t?null:+t+""==t?+t:/^[\[\{]/.test(t)?r.parseJSON(t):t):t}catch(e){return t}}function tt(t,e){e(t);for(var n=0,r=t.childNodes.length;r>n;n++)tt(t.childNodes[n],e)}var e,n,r,i,O,P,o=[],s=o.concat,a=o.filter,u=o.slice,f=t.document,c={},l={},h={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},p=/^\s*<(\w+|!)[^>]*>/,d=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,m=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,g=/^(?:body|html)$/i,v=/([A-Z])/g,y=["val","css","html","text","data","width","height","offset"],x=["after","prepend","before","append"],b=f.createElement("table"),E=f.createElement("tr"),j={tr:f.createElement("tbody"),tbody:b,thead:b,tfoot:b,td:E,th:E,"*":f.createElement("div")},w=/complete|loaded|interactive/,T=/^[\w-]*$/,S={},C=S.toString,N={},A=f.createElement("div"),D={tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},L=Array.isArray||function(t){return t instanceof Array};return N.matches=function(t,e){if(!e||!t||1!==t.nodeType)return!1;var n=t.matches||t.webkitMatchesSelector||t.mozMatchesSelector||t.oMatchesSelector||t.matchesSelector;if(n)return n.call(t,e);var r,i=t.parentNode,o=!i;return o&&(i=A).appendChild(t),r=~N.qsa(i,e).indexOf(t),o&&A.removeChild(t),r},O=function(t){return t.replace(/-+(.)?/g,function(t,e){return e?e.toUpperCase():""})},P=function(t){return a.call(t,function(e,n){return t.indexOf(e)==n})},N.fragment=function(t,n,i){var o,s,a;return d.test(t)&&(o=r(f.createElement(RegExp.$1))),o||(t.replace&&(t=t.replace(m,"<$1>")),n===e&&(n=p.test(t)&&RegExp.$1),n in j||(n="*"),a=j[n],a.innerHTML=""+t,o=r.each(u.call(a.childNodes),function(){a.removeChild(this)})),Z(i)&&(s=r(o),r.each(i,function(t,e){y.indexOf(t)>-1?s[t](e):s.attr(t,e)})),o},N.Z=function(t,e){return new X(t,e)},N.isZ=function(t){return t instanceof N.Z},N.init=function(t,n){var i;if(!t)return N.Z();if("string"==typeof t)if(t=t.trim(),"<"==t[0]&&p.test(t))i=N.fragment(t,RegExp.$1,n),t=null;else{if(n!==e)return r(n).find(t);i=N.qsa(f,t)}else{if(F(t))return r(f).ready(t);if(N.isZ(t))return t;if(L(t))i=q(t);else if(R(t))i=[t],t=null;else if(p.test(t))i=N.fragment(t.trim(),RegExp.$1,n),t=null;else{if(n!==e)return r(n).find(t);i=N.qsa(f,t)}}return N.Z(i,t)},r=function(t,e){return N.init(t,e)},r.extend=function(t){var e,n=u.call(arguments,1);return"boolean"==typeof t&&(e=t,t=n.shift()),n.forEach(function(n){J(t,n,e)}),t},N.qsa=function(t,e){var n,r="#"==e[0],i=!r&&"."==e[0],o=r||i?e.slice(1):e,s=T.test(o);return t.getElementById&&s&&r?(n=t.getElementById(o))?[n]:[]:1!==t.nodeType&&9!==t.nodeType&&11!==t.nodeType?[]:u.call(s&&!r&&t.getElementsByClassName?i?t.getElementsByClassName(o):t.getElementsByTagName(e):t.querySelectorAll(e))},r.contains=f.documentElement.contains?function(t,e){return t!==e&&t.contains(e)}:function(t,e){for(;e&&(e=e.parentNode);)if(e===t)return!0;return!1},r.type=$,r.isFunction=F,r.isWindow=k,r.isArray=L,r.isPlainObject=Z,r.isEmptyObject=function(t){var e;for(e in t)return!1;return!0},r.isNumeric=function(t){var e=Number(t),n=typeof t;return null!=t&&"boolean"!=n&&("string"!=n||t.length)&&!isNaN(e)&&isFinite(e)||!1},r.inArray=function(t,e,n){return o.indexOf.call(e,t,n)},r.camelCase=O,r.trim=function(t){return null==t?"":String.prototype.trim.call(t)},r.uuid=0,r.support={},r.expr={},r.noop=function(){},r.map=function(t,e){var n,i,o,r=[];if(z(t))for(i=0;i=0?t:t+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){null!=this.parentNode&&this.parentNode.removeChild(this)})},each:function(t){return o.every.call(this,function(e,n){return t.call(e,n,e)!==!1}),this},filter:function(t){return F(t)?this.not(this.not(t)):r(a.call(this,function(e){return N.matches(e,t)}))},add:function(t,e){return r(P(this.concat(r(t,e))))},is:function(t){return this.length>0&&N.matches(this[0],t)},not:function(t){var n=[];if(F(t)&&t.call!==e)this.each(function(e){t.call(this,e)||n.push(this)});else{var i="string"==typeof t?this.filter(t):z(t)&&F(t.item)?u.call(t):r(t);this.forEach(function(t){i.indexOf(t)<0&&n.push(t)})}return r(n)},has:function(t){return this.filter(function(){return R(t)?r.contains(this,t):r(this).find(t).size()})},eq:function(t){return-1===t?this.slice(t):this.slice(t,+t+1)},first:function(){var t=this[0];return t&&!R(t)?t:r(t)},last:function(){var t=this[this.length-1];return t&&!R(t)?t:r(t)},find:function(t){var e,n=this;return e=t?"object"==typeof t?r(t).filter(function(){var t=this;return o.some.call(n,function(e){return r.contains(e,t)})}):1==this.length?r(N.qsa(this[0],t)):this.map(function(){return N.qsa(this,t)}):r()},closest:function(t,e){var n=[],i="object"==typeof t&&r(t);return this.each(function(r,o){for(;o&&!(i?i.indexOf(o)>=0:N.matches(o,t));)o=o!==e&&!M(o)&&o.parentNode;o&&n.indexOf(o)<0&&n.push(o)}),r(n)},parents:function(t){for(var e=[],n=this;n.length>0;)n=r.map(n,function(t){return(t=t.parentNode)&&!M(t)&&e.indexOf(t)<0?(e.push(t),t):void 0});return W(e,t)},parent:function(t){return W(P(this.pluck("parentNode")),t)},children:function(t){return W(this.map(function(){return U(this)}),t)},contents:function(){return this.map(function(){return this.contentDocument||u.call(this.childNodes)})},siblings:function(t){return W(this.map(function(t,e){return a.call(U(e.parentNode),function(t){return t!==e})}),t)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(t){return r.map(this,function(e){return e[t]})},show:function(){return this.each(function(){"none"==this.style.display&&(this.style.display=""),"none"==getComputedStyle(this,"").getPropertyValue("display")&&(this.style.display=B(this.nodeName))})},replaceWith:function(t){return this.before(t).remove()},wrap:function(t){var e=F(t);if(this[0]&&!e)var n=r(t).get(0),i=n.parentNode||this.length>1;return this.each(function(o){r(this).wrapAll(e?t.call(this,o):i?n.cloneNode(!0):n)})},wrapAll:function(t){if(this[0]){r(this[0]).before(t=r(t));for(var e;(e=t.children()).length;)t=e.first();r(t).append(this)}return this},wrapInner:function(t){var e=F(t);return this.each(function(n){var i=r(this),o=i.contents(),s=e?t.call(this,n):t;o.length?o.wrapAll(s):i.append(s)})},unwrap:function(){return this.parent().each(function(){r(this).replaceWith(r(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(t){return this.each(function(){var n=r(this);(t===e?"none"==n.css("display"):t)?n.show():n.hide()})},prev:function(t){return r(this.pluck("previousElementSibling")).filter(t||"*")},next:function(t){return r(this.pluck("nextElementSibling")).filter(t||"*")},html:function(t){return 0 in arguments?this.each(function(e){var n=this.innerHTML;r(this).empty().append(Y(this,t,e,n))}):0 in this?this[0].innerHTML:null},text:function(t){return 0 in arguments?this.each(function(e){var n=Y(this,t,e,this.textContent);this.textContent=null==n?"":""+n}):0 in this?this.pluck("textContent").join(""):null},attr:function(t,r){var i;return"string"!=typeof t||1 in arguments?this.each(function(e){if(1===this.nodeType)if(R(t))for(n in t)G(this,n,t[n]);else G(this,t,Y(this,r,e,this.getAttribute(t)))}):0 in this&&1==this[0].nodeType&&null!=(i=this[0].getAttribute(t))?i:e},removeAttr:function(t){return this.each(function(){1===this.nodeType&&t.split(" ").forEach(function(t){G(this,t)},this)})},prop:function(t,e){return t=D[t]||t,1 in arguments?this.each(function(n){this[t]=Y(this,e,n,this[t])}):this[0]&&this[0][t]},removeProp:function(t){return t=D[t]||t,this.each(function(){delete this[t]})},data:function(t,n){var r="data-"+t.replace(v,"-$1").toLowerCase(),i=1 in arguments?this.attr(r,n):this.attr(r);return null!==i?Q(i):e},val:function(t){return 0 in arguments?(null==t&&(t=""),this.each(function(e){this.value=Y(this,t,e,this.value)})):this[0]&&(this[0].multiple?r(this[0]).find("option").filter(function(){return this.selected}).pluck("value"):this[0].value)},offset:function(e){if(e)return this.each(function(t){var n=r(this),i=Y(this,e,t,n.offset()),o=n.offsetParent().offset(),s={top:i.top-o.top,left:i.left-o.left};"static"==n.css("position")&&(s.position="relative"),n.css(s)});if(!this.length)return null;if(f.documentElement!==this[0]&&!r.contains(f.documentElement,this[0]))return{top:0,left:0};var n=this[0].getBoundingClientRect();return{left:n.left+t.pageXOffset,top:n.top+t.pageYOffset,width:Math.round(n.width),height:Math.round(n.height)}},css:function(t,e){if(arguments.length<2){var i=this[0];if("string"==typeof t){if(!i)return;return i.style[O(t)]||getComputedStyle(i,"").getPropertyValue(t)}if(L(t)){if(!i)return;var o={},s=getComputedStyle(i,"");return r.each(t,function(t,e){o[e]=i.style[O(e)]||s.getPropertyValue(e)}),o}}var a="";if("string"==$(t))e||0===e?a=I(t)+":"+_(t,e):this.each(function(){this.style.removeProperty(I(t))});else for(n in t)t[n]||0===t[n]?a+=I(n)+":"+_(n,t[n])+";":this.each(function(){this.style.removeProperty(I(n))});return this.each(function(){this.style.cssText+=";"+a})},index:function(t){return t?this.indexOf(r(t)[0]):this.parent().children().indexOf(this[0])},hasClass:function(t){return t?o.some.call(this,function(t){return this.test(K(t))},V(t)):!1},addClass:function(t){return t?this.each(function(e){if("className"in this){i=[];var n=K(this),o=Y(this,t,e,n);o.split(/\s+/g).forEach(function(t){r(this).hasClass(t)||i.push(t)},this),i.length&&K(this,n+(n?" ":"")+i.join(" "))}}):this},removeClass:function(t){return this.each(function(n){if("className"in this){if(t===e)return K(this,"");i=K(this),Y(this,t,n,i).split(/\s+/g).forEach(function(t){i=i.replace(V(t)," ")}),K(this,i.trim())}})},toggleClass:function(t,n){return t?this.each(function(i){var o=r(this),s=Y(this,t,i,K(this));s.split(/\s+/g).forEach(function(t){(n===e?!o.hasClass(t):n)?o.addClass(t):o.removeClass(t)})}):this},scrollTop:function(t){if(this.length){var n="scrollTop"in this[0];return t===e?n?this[0].scrollTop:this[0].pageYOffset:this.each(n?function(){this.scrollTop=t}:function(){this.scrollTo(this.scrollX,t)})}},scrollLeft:function(t){if(this.length){var n="scrollLeft"in this[0];return t===e?n?this[0].scrollLeft:this[0].pageXOffset:this.each(n?function(){this.scrollLeft=t}:function(){this.scrollTo(t,this.scrollY)})}},position:function(){if(this.length){var t=this[0],e=this.offsetParent(),n=this.offset(),i=g.test(e[0].nodeName)?{top:0,left:0}:e.offset();return n.top-=parseFloat(r(t).css("margin-top"))||0,n.left-=parseFloat(r(t).css("margin-left"))||0,i.top+=parseFloat(r(e[0]).css("border-top-width"))||0,i.left+=parseFloat(r(e[0]).css("border-left-width"))||0,{top:n.top-i.top,left:n.left-i.left}}},offsetParent:function(){return this.map(function(){for(var t=this.offsetParent||f.body;t&&!g.test(t.nodeName)&&"static"==r(t).css("position");)t=t.offsetParent;return t})}},r.fn.detach=r.fn.remove,["width","height"].forEach(function(t){var n=t.replace(/./,function(t){return t[0].toUpperCase()});r.fn[t]=function(i){var o,s=this[0];return i===e?k(s)?s["inner"+n]:M(s)?s.documentElement["scroll"+n]:(o=this.offset())&&o[t]:this.each(function(e){s=r(this),s.css(t,Y(this,i,e,s[t]()))})}}),x.forEach(function(n,i){var o=i%2;r.fn[n]=function(){var n,a,s=r.map(arguments,function(t){var i=[];return n=$(t),"array"==n?(t.forEach(function(t){return t.nodeType!==e?i.push(t):r.zepto.isZ(t)?i=i.concat(t.get()):void(i=i.concat(N.fragment(t)))}),i):"object"==n||null==t?t:N.fragment(t)}),u=this.length>1;return s.length<1?this:this.each(function(e,n){a=o?n:n.parentNode,n=0==i?n.nextSibling:1==i?n.firstChild:2==i?n:null;var c=r.contains(f.documentElement,a);s.forEach(function(e){if(u)e=e.cloneNode(!0);else if(!a)return r(e).remove();a.insertBefore(e,n),c&&tt(e,function(e){if(!(null==e.nodeName||"SCRIPT"!==e.nodeName.toUpperCase()||e.type&&"text/javascript"!==e.type||e.src)){var n=e.ownerDocument?e.ownerDocument.defaultView:t;n.eval.call(n,e.innerHTML)}})})})},r.fn[o?n+"To":"insert"+(i?"Before":"After")]=function(t){return r(t)[n](this),this}}),N.Z.prototype=X.prototype=r.fn,N.uniq=P,N.deserializeValue=Q,r.zepto=N,r}();return t.Zepto=e,void 0===t.$&&(t.$=e),function(e){function h(t){return t._zid||(t._zid=n++)}function p(t,e,n,r){if(e=d(e),e.ns)var i=m(e.ns);return(a[h(t)]||[]).filter(function(t){return t&&(!e.e||t.e==e.e)&&(!e.ns||i.test(t.ns))&&(!n||h(t.fn)===h(n))&&(!r||t.sel==r)})}function d(t){var e=(""+t).split(".");return{e:e[0],ns:e.slice(1).sort().join(" ")}}function m(t){return new RegExp("(?:^| )"+t.replace(" "," .* ?")+"(?: |$)")}function g(t,e){return t.del&&!f&&t.e in c||!!e}function v(t){return l[t]||f&&c[t]||t}function y(t,n,i,o,s,u,f){var c=h(t),p=a[c]||(a[c]=[]);n.split(/\s/).forEach(function(n){if("ready"==n)return e(document).ready(i);var a=d(n);a.fn=i,a.sel=s,a.e in l&&(i=function(t){var n=t.relatedTarget;return!n||n!==this&&!e.contains(this,n)?a.fn.apply(this,arguments):void 0}),a.del=u;var c=u||i;a.proxy=function(e){if(e=T(e),!e.isImmediatePropagationStopped()){e.data=o;var n=c.apply(t,e._args==r?[e]:[e].concat(e._args));return n===!1&&(e.preventDefault(),e.stopPropagation()),n}},a.i=p.length,p.push(a),"addEventListener"in t&&t.addEventListener(v(a.e),a.proxy,g(a,f))})}function x(t,e,n,r,i){var o=h(t);(e||"").split(/\s/).forEach(function(e){p(t,e,n,r).forEach(function(e){delete a[o][e.i],"removeEventListener"in t&&t.removeEventListener(v(e.e),e.proxy,g(e,i))})})}function T(t,n){return(n||!t.isDefaultPrevented)&&(n||(n=t),e.each(w,function(e,r){var i=n[e];t[e]=function(){return this[r]=b,i&&i.apply(n,arguments)},t[r]=E}),t.timeStamp||(t.timeStamp=Date.now()),(n.defaultPrevented!==r?n.defaultPrevented:"returnValue"in n?n.returnValue===!1:n.getPreventDefault&&n.getPreventDefault())&&(t.isDefaultPrevented=b)),t}function S(t){var e,n={originalEvent:t};for(e in t)j.test(e)||t[e]===r||(n[e]=t[e]);return T(n,t)}var r,n=1,i=Array.prototype.slice,o=e.isFunction,s=function(t){return"string"==typeof t},a={},u={},f="onfocusin"in t,c={focus:"focusin",blur:"focusout"},l={mouseenter:"mouseover",mouseleave:"mouseout"};u.click=u.mousedown=u.mouseup=u.mousemove="MouseEvents",e.event={add:y,remove:x},e.proxy=function(t,n){var r=2 in arguments&&i.call(arguments,2);if(o(t)){var a=function(){return t.apply(n,r?r.concat(i.call(arguments)):arguments)};return a._zid=h(t),a}if(s(n))return r?(r.unshift(t[n],t),e.proxy.apply(null,r)):e.proxy(t[n],t);throw new TypeError("expected function")},e.fn.bind=function(t,e,n){return this.on(t,e,n)},e.fn.unbind=function(t,e){return this.off(t,e)},e.fn.one=function(t,e,n,r){return this.on(t,e,n,r,1)};var b=function(){return!0},E=function(){return!1},j=/^([A-Z]|returnValue$|layer[XY]$|webkitMovement[XY]$)/,w={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};e.fn.delegate=function(t,e,n){return this.on(e,t,n)},e.fn.undelegate=function(t,e,n){return this.off(e,t,n)},e.fn.live=function(t,n){return e(document.body).delegate(this.selector,t,n),this},e.fn.die=function(t,n){return e(document.body).undelegate(this.selector,t,n),this},e.fn.on=function(t,n,a,u,f){var c,l,h=this;return t&&!s(t)?(e.each(t,function(t,e){h.on(t,n,a,e,f)}),h):(s(n)||o(u)||u===!1||(u=a,a=n,n=r),(u===r||a===!1)&&(u=a,a=r),u===!1&&(u=E),h.each(function(r,o){f&&(c=function(t){return x(o,t.type,u),u.apply(this,arguments)}),n&&(l=function(t){var r,s=e(t.target).closest(n,o).get(0);return s&&s!==o?(r=e.extend(S(t),{currentTarget:s,liveFired:o}),(c||u).apply(s,[r].concat(i.call(arguments,1)))):void 0}),y(o,t,u,a,n,l||c)}))},e.fn.off=function(t,n,i){var a=this;return t&&!s(t)?(e.each(t,function(t,e){a.off(t,n,e)}),a):(s(n)||o(i)||i===!1||(i=n,n=r),i===!1&&(i=E),a.each(function(){x(this,t,i,n)}))},e.fn.trigger=function(t,n){return t=s(t)||e.isPlainObject(t)?e.Event(t):T(t),t._args=n,this.each(function(){t.type in c&&"function"==typeof this[t.type]?this[t.type]():"dispatchEvent"in this?this.dispatchEvent(t):e(this).triggerHandler(t,n)})},e.fn.triggerHandler=function(t,n){var r,i;return this.each(function(o,a){r=S(s(t)?e.Event(t):t),r._args=n,r.target=a,e.each(p(a,t.type||t),function(t,e){return i=e.proxy(r),r.isImmediatePropagationStopped()?!1:void 0})}),i},"focusin focusout focus blur load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(t){e.fn[t]=function(e){return 0 in arguments?this.bind(t,e):this.trigger(t)}}),e.Event=function(t,e){s(t)||(e=t,t=e.type);var n=document.createEvent(u[t]||"Events"),r=!0;if(e)for(var i in e)"bubbles"==i?r=!!e[i]:n[i]=e[i];return n.initEvent(t,r,!0),T(n)}}(e),function(e){function p(t,n,r){var i=e.Event(n);return e(t).trigger(i,r),!i.isDefaultPrevented()}function d(t,e,n,i){return t.global?p(e||r,n,i):void 0}function m(t){t.global&&0===e.active++&&d(t,null,"ajaxStart")}function g(t){t.global&&!--e.active&&d(t,null,"ajaxStop")}function v(t,e){var n=e.context;return e.beforeSend.call(n,t,e)===!1||d(e,n,"ajaxBeforeSend",[t,e])===!1?!1:void d(e,n,"ajaxSend",[t,e])}function y(t,e,n,r){var i=n.context,o="success";n.success.call(i,t,o,e),r&&r.resolveWith(i,[t,o,e]),d(n,i,"ajaxSuccess",[e,n,t]),b(o,e,n)}function x(t,e,n,r,i){var o=r.context;r.error.call(o,n,e,t),i&&i.rejectWith(o,[n,e,t]),d(r,o,"ajaxError",[n,r,t||e]),b(e,n,r)}function b(t,e,n){var r=n.context;n.complete.call(r,e,t),d(n,r,"ajaxComplete",[e,n]),g(n)}function E(t,e,n){if(n.dataFilter==j)return t;var r=n.context;return n.dataFilter.call(r,t,e)}function j(){}function w(t){return t&&(t=t.split(";",2)[0]),t&&(t==c?"html":t==f?"json":a.test(t)?"script":u.test(t)&&"xml")||"text"}function T(t,e){return""==e?t:(t+"&"+e).replace(/[&?]{1,2}/,"?")}function S(t){t.processData&&t.data&&"string"!=e.type(t.data)&&(t.data=e.param(t.data,t.traditional)),!t.data||t.type&&"GET"!=t.type.toUpperCase()&&"jsonp"!=t.dataType||(t.url=T(t.url,t.data),t.data=void 0)}function C(t,n,r,i){return e.isFunction(n)&&(i=r,r=n,n=void 0),e.isFunction(r)||(i=r,r=void 0),{url:t,data:n,success:r,dataType:i}}function O(t,n,r,i){var o,s=e.isArray(n),a=e.isPlainObject(n);e.each(n,function(n,u){o=e.type(u),i&&(n=r?i:i+"["+(a||"object"==o||"array"==o?n:"")+"]"),!i&&s?t.add(u.name,u.value):"array"==o||!r&&"object"==o?O(t,u,r,n):t.add(n,u)})}var i,o,n=+new Date,r=t.document,s=/)<[^<]*)*<\/script>/gi,a=/^(?:text|application)\/javascript/i,u=/^(?:text|application)\/xml/i,f="application/json",c="text/html",l=/^\s*$/,h=r.createElement("a");h.href=t.location.href,e.active=0,e.ajaxJSONP=function(i,o){if(!("type"in i))return e.ajax(i);var c,p,s=i.jsonpCallback,a=(e.isFunction(s)?s():s)||"Zepto"+n++,u=r.createElement("script"),f=t[a],l=function(t){e(u).triggerHandler("error",t||"abort")},h={abort:l};return o&&o.promise(h),e(u).on("load error",function(n,r){clearTimeout(p),e(u).off().remove(),"error"!=n.type&&c?y(c[0],h,i,o):x(null,r||"error",h,i,o),t[a]=f,c&&e.isFunction(f)&&f(c[0]),f=c=void 0}),v(h,i)===!1?(l("abort"),h):(t[a]=function(){c=arguments},u.src=i.url.replace(/\?(.+)=\?/,"?$1="+a),r.head.appendChild(u),i.timeout>0&&(p=setTimeout(function(){l("timeout")},i.timeout)),h)},e.ajaxSettings={type:"GET",beforeSend:j,success:j,error:j,complete:j,context:null,global:!0,xhr:function(){return new t.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript, application/x-javascript",json:f,xml:"application/xml, text/xml",html:c,text:"text/plain"},crossDomain:!1,timeout:0,processData:!0,cache:!0,dataFilter:j},e.ajax=function(n){var u,f,s=e.extend({},n||{}),a=e.Deferred&&e.Deferred();for(i in e.ajaxSettings)void 0===s[i]&&(s[i]=e.ajaxSettings[i]);m(s),s.crossDomain||(u=r.createElement("a"),u.href=s.url,u.href=u.href,s.crossDomain=h.protocol+"//"+h.host!=u.protocol+"//"+u.host),s.url||(s.url=t.location.toString()),(f=s.url.indexOf("#"))>-1&&(s.url=s.url.slice(0,f)),S(s);var c=s.dataType,p=/\?.+=\?/.test(s.url);if(p&&(c="jsonp"),s.cache!==!1&&(n&&n.cache===!0||"script"!=c&&"jsonp"!=c)||(s.url=T(s.url,"_="+Date.now())),"jsonp"==c)return p||(s.url=T(s.url,s.jsonp?s.jsonp+"=?":s.jsonp===!1?"":"callback=?")),e.ajaxJSONP(s,a);var P,d=s.accepts[c],g={},b=function(t,e){g[t.toLowerCase()]=[t,e]},C=/^([\w-]+:)\/\//.test(s.url)?RegExp.$1:t.location.protocol,N=s.xhr(),O=N.setRequestHeader;if(a&&a.promise(N),s.crossDomain||b("X-Requested-With","XMLHttpRequest"),b("Accept",d||"*/*"),(d=s.mimeType||d)&&(d.indexOf(",")>-1&&(d=d.split(",",2)[0]),N.overrideMimeType&&N.overrideMimeType(d)),(s.contentType||s.contentType!==!1&&s.data&&"GET"!=s.type.toUpperCase())&&b("Content-Type",s.contentType||"application/x-www-form-urlencoded"),s.headers)for(o in s.headers)b(o,s.headers[o]);if(N.setRequestHeader=b,N.onreadystatechange=function(){if(4==N.readyState){N.onreadystatechange=j,clearTimeout(P);var t,n=!1;if(N.status>=200&&N.status<300||304==N.status||0==N.status&&"file:"==C){if(c=c||w(s.mimeType||N.getResponseHeader("content-type")),"arraybuffer"==N.responseType||"blob"==N.responseType)t=N.response;else{t=N.responseText;try{t=E(t,c,s),"script"==c?(1,eval)(t):"xml"==c?t=N.responseXML:"json"==c&&(t=l.test(t)?null:e.parseJSON(t))}catch(r){n=r}if(n)return x(n,"parsererror",N,s,a)}y(t,N,s,a)}else x(N.statusText||null,N.status?"error":"abort",N,s,a)}},v(N,s)===!1)return N.abort(),x(null,"abort",N,s,a),N;var A="async"in s?s.async:!0;if(N.open(s.type,s.url,A,s.username,s.password),s.xhrFields)for(o in s.xhrFields)N[o]=s.xhrFields[o];for(o in g)O.apply(N,g[o]);return s.timeout>0&&(P=setTimeout(function(){N.onreadystatechange=j,N.abort(),x(null,"timeout",N,s,a)},s.timeout)),N.send(s.data?s.data:null),N},e.get=function(){return e.ajax(C.apply(null,arguments))},e.post=function(){var t=C.apply(null,arguments);return t.type="POST",e.ajax(t)},e.getJSON=function(){var t=C.apply(null,arguments);return t.dataType="json",e.ajax(t)},e.fn.load=function(t,n,r){if(!this.length)return this;var a,i=this,o=t.split(/\s/),u=C(t,n,r),f=u.success;return o.length>1&&(u.url=o[0],a=o[1]),u.success=function(t){i.html(a?e("
").html(t.replace(s,"")).find(a):t),f&&f.apply(i,arguments)},e.ajax(u),this};var N=encodeURIComponent;e.param=function(t,n){var r=[];return r.add=function(t,n){e.isFunction(n)&&(n=n()),null==n&&(n=""),this.push(N(t)+"="+N(n))},O(r,t,n),r.join("&").replace(/%20/g,"+")}}(e),function(t){t.fn.serializeArray=function(){var e,n,r=[],i=function(t){return t.forEach?t.forEach(i):void r.push({name:e,value:t})};return this[0]&&t.each(this[0].elements,function(r,o){n=o.type,e=o.name,e&&"fieldset"!=o.nodeName.toLowerCase()&&!o.disabled&&"submit"!=n&&"reset"!=n&&"button"!=n&&"file"!=n&&("radio"!=n&&"checkbox"!=n||o.checked)&&i(t(o).val())}),r},t.fn.serialize=function(){var t=[];return this.serializeArray().forEach(function(e){t.push(encodeURIComponent(e.name)+"="+encodeURIComponent(e.value))}),t.join("&")},t.fn.submit=function(e){if(0 in arguments)this.bind("submit",e);else if(this.length){var n=t.Event("submit");this.eq(0).trigger(n),n.isDefaultPrevented()||this.get(0).submit()}return this}}(e),function(){try{getComputedStyle(void 0)}catch(e){var n=getComputedStyle;t.getComputedStyle=function(t,e){try{return n(t,e)}catch(r){return null}}}}(),e}); -------------------------------------------------------------------------------- /tests/style.css: -------------------------------------------------------------------------------- 1 | *{box-sizing:border-box;} 2 | body{font-family:Arial, Helvetica, sans-serif;} 3 | .header{height:108px;} 4 | .button{color:#fff; background:#56bf94; padding:7px 15px; border-radius:4px;box-shadow:3px 3px 0px rgba(0,0,0,0.15);} 5 | .button:link{text-decoration:none;} 6 | .button:hover{background:#1bcd84;} 7 | .row{width:100%; box-sizing:border-box;} 8 | .row:after{visibility:hidden; display:block; font-size:0; content:" "; clear:both; height:0;} 9 | .col{float:left; position:relative; display:inline-block;} 10 | .pad{padding:15px;} 11 | .pad-lg{padding:30px;} 12 | .pad-right{padding-right:15px;} 13 | .pad-width-lg{padding-left:30px; padding-right:30px;} 14 | .pad-height{padding-top:15px; padding-bottom:15px;} --------------------------------------------------------------------------------