Greasy Fork镜像 支持简体中文。

CodeFelony JS Library

A JavaScript library used by CodeFelony

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.gf.qytechs.cn/scripts/9003/44596/CodeFelony%20JS%20Library.js

  1. // ==UserScript==
  2. // @name CodeFelony JS Library
  3. // @namespace https://gf.qytechs.cn/en/users/10166-moriarty
  4. // @description A JavaScript library used by CodeFelony
  5. // @include *
  6. // @copyright (c) 2015 CodeFelony. All Rights Reserved
  7. // @author Moriarty
  8. // @version 1.3.1
  9. // @license LGPL version 3 or any later version; http://www.gnu.org/copyleft/lgpl.html
  10. // @grant GM_addStyle
  11. // ==/UserScript==
  12.  
  13. /**
  14. WIKI ==> https://github.com/codefelony/cfl/wiki/
  15. **/
  16.  
  17. (function (window, undefined) {
  18.  
  19. 'use strict'; // use strict mode in ECMAScript-5
  20.  
  21. var version = '1.3.1'; // this will be used for CFL.prototype.version
  22. var intervals = []; // for the setInterval/clearInterval methods
  23.  
  24. // regular expressions
  25. var rSelector = /^\*|^\.[a-z][\w\d-]*|^#[^ ]+|^[a-z]+|^\[a-z]+/i; // matches a CSS selector
  26. var rXpath = /^(\.*\/{1,2})+[a-zA-Z\*]+/; // matches an XPath query
  27. var rHTML = /<[^>]+>/; // matches a string of HTML
  28. var rHyphenated = /-([a-zA-Z])/g; // matches alphabetic, hyphenated strings
  29. var rElementObject = /^\[object HTML([a-zA-Z]+)?Element\]$/; // matches the toString value of an element
  30. var rWindowObject = /^\[object Window\]$/; // matches the toString value of a window object
  31. var rValidVarname = /^[a-zA-Z$_][a-zA-Z0-9$_]*$/; // matches a valid variable name
  32.  
  33. // compatibility methods for browsers that don't support ECMAScript-5 completely
  34. var compat = {
  35. 'arr_indexOf' : function (searchElement, fromIndex) {
  36. var index = parseInt(fromIndex || 0, 10), len = this.length;
  37. index = index < 0 ? len + index : index; // handle negative fromIndex
  38. index = !(index > 0) ? 0 : index; // handle out of range and/or NaN fromIndex
  39.  
  40. while (index < len && index >= 0) {
  41. if (this[index] === searchElement) {
  42. return index;
  43. }
  44. index += 1;
  45. }
  46.  
  47. return -1;
  48. },
  49. /*
  50. 'filter' : function (fn, oThis) {
  51. var index, value, len = this.length, ret = [];
  52.  
  53. for (index = 0; index < len; index += 1) {
  54. value = this[index];
  55. if ( fn.call(oThis, value, index, this) ) {
  56. ret.push(value);
  57. }
  58. }
  59.  
  60. return ret;
  61. },
  62. */
  63. 'forEach' : function (fn, oThis) {
  64. var index, len;
  65.  
  66. for (index = 0, len = this.length; index < len; index += 1) {
  67. fn.call(oThis, this[index], index, this);
  68. }
  69. },
  70. 'map' : function (fn, oThis) {
  71. var index, newArr = [], len;
  72.  
  73. for (index = 0, len = this.length; index < len; index += 1) {
  74. newArr[index] = fn.call(oThis, this[index], index, this);
  75. }
  76.  
  77. return newArr;
  78. },
  79. 'reduce' : function (fn, initialValue) {
  80. var index, len, value, isValueSet = false;
  81.  
  82. if (arguments.length > 1) {
  83. value = initialValue;
  84. isValueSet = true;
  85. }
  86.  
  87. for (index = 0, len = this.length; index < len; index += 1) {
  88. if (isValueSet) {
  89. value = fn(value, this[index], index, this);
  90. } else {
  91. value = this[index];
  92. isValueSet = true;
  93. }
  94. }
  95.  
  96. return value;
  97. }
  98. };
  99.  
  100. // gets a method from an object's prototype. returns undefined if not found
  101. var getMethod = function (obj, method) {
  102. if (typeof XPCNativeWrapper === 'function' && typeof XPCNativeWrapper.unwrap === 'function') {
  103. obj = XPCNativeWrapper.unwrap(obj);
  104. } else if (obj.wrappedJSObject) {
  105. obj = obj.wrappedJSObject;
  106. }
  107.  
  108. if (obj.prototype && typeof obj.prototype[method] === 'function') {
  109. return obj.prototype[method];
  110. }
  111. };
  112.  
  113. // original methods for some common uses
  114. var core = {
  115. // array
  116. 'arr_indexOf' : getMethod(Array, 'indexOf') || compat.arr_indexOf,
  117. 'concat' : getMethod(Array, 'concat'),
  118. 'filter' : getMethod(Array, 'filter') || compat.filter,
  119. 'forEach' : getMethod(Array, 'forEach') || compat.forEach,
  120. 'map' : getMethod(Array, 'map') || compat.map,
  121. 'reduce' : getMethod(Array, 'reduce') || compat.reduce,
  122. 'slice' : getMethod(Array, 'slice'),
  123.  
  124. // object
  125. 'hasOwnProperty' : getMethod(Object, 'hasOwnProperty'),
  126. 'toString' : getMethod(Object, 'toString'),
  127. };
  128.  
  129. var CFL = function CFL(selector, context) {
  130. return new CFL.fn.init(selector, context);
  131. };
  132.  
  133. // a simple class for dealing with event listener handlers
  134. var handlers = {
  135. stack : [],
  136.  
  137. add : function (thisElement, type, fn) {
  138. this.stack.push({
  139. element : thisElement,
  140. type : type,
  141. fn : fn
  142. });
  143. },
  144.  
  145. get : function (thisElement, type) {
  146. var events = [];
  147. type = typeof type === 'string' ? type : '*';
  148.  
  149. CFL.each(this.stack, function (thisEventObj) {
  150. if (thisElement === thisEventObj.element) {
  151. if (type === '*' || thisEventObj.type === type) {
  152. events.push(thisEventObj);
  153. }
  154. }
  155. });
  156.  
  157. return events;
  158. },
  159.  
  160. remove : function (thisElement, type) {
  161. var handlerIndices = [], that = this;
  162.  
  163. // find all the indices of what we need to remove
  164. CFL.each(handlers.get(thisElement, type), function (thisEventObj, index, array) {
  165. handlerIndices.push(
  166. core.arr_indexOf.call(that.stack, thisEventObj)
  167. );
  168. });
  169.  
  170. // remove all the indices here, using a separate array of indices
  171. // we can't do this as we loop over the (stack) array itself, because
  172. // we would be removing values as they are being iterated through
  173. CFL.each(handlerIndices, function (thisIndex) {
  174. that.stack.splice(thisIndex, 1);
  175. });
  176. }
  177. };
  178.  
  179. // Node.prototype.matchesSelector compat for vendor prefixes
  180. function matchesSelector(element, selector) {
  181. if (element && typeof selector === 'string') {
  182. if (typeof element.mozMatchesSelector === 'function') {
  183. // Mozilla
  184. return element.mozMatchesSelector(selector);
  185. } else if (typeof element.webkitMatchesSelector === 'function') {
  186. // Webkit
  187. return element.webkitMatchesSelector(selector);
  188. } else if (typeof element.oMatchesSelector === 'function') {
  189. // Opera
  190. return element.oMatchesSelector(selector);
  191. } else if (typeof element.msMatchesSelector === 'function') {
  192. // IE
  193. return element.msMatchesSelector(selector);
  194. }
  195. }
  196.  
  197. return false;
  198. }
  199.  
  200. // calls 'this' with the first parameter as the first argument
  201. function call(a) {
  202. return this(a);
  203. }
  204.  
  205. function toCamelCase(string) {
  206. return string.replace(rHyphenated, function (fullMatch, firstGroup) {
  207. return firstGroup.toUpperCase();
  208. });
  209. }
  210.  
  211. // walkTheDom by Douglas Crockford
  212. function walkTheDom(node, func) {
  213. func(node);
  214. node = node.firstChild;
  215.  
  216. while (node) {
  217. walkTheDom(node, func);
  218. node = node.nextSibling;
  219. }
  220. }
  221.  
  222. // can pluck a key out of an object
  223. function pluck(obj) {
  224. var subs = this.split('.'),
  225. ret = obj, i;
  226.  
  227. for (i = 0; i < subs.length; i += 1) {
  228. ret = ret[ subs[i] ];
  229. if (ret == null) {
  230. return '';
  231. }
  232. }
  233.  
  234. return ret;
  235. }
  236.  
  237. function sum(curValue, nextValue) {
  238. return curValue + nextValue;
  239. }
  240.  
  241. function sumInt(curValue, nextValue) {
  242. return parseInt(curValue, 10) + parseInt(nextValue, 10);
  243. }
  244.  
  245. // internal function for throwing errors, so the user gets
  246. // some sort of hint as to why their operation failed
  247. function error(errorString) {
  248. if (typeof console !== 'undefined' && typeof console.error === 'function') {
  249. console.error(errorString);
  250. }
  251.  
  252. return null; // always return null
  253. }
  254.  
  255. // will copy an element and return a new copy with the same event listeners
  256. function cloneElement(thisElement) {
  257. var newElement = thisElement.cloneNode(true);
  258.  
  259. // clone event listeners of element
  260. CFL.each(handlers.get(thisElement), function (thisEventObj) {
  261. CFL.addEvent(newElement, thisEventObj.type, thisEventObj.fn);
  262. });
  263.  
  264. return newElement;
  265. }
  266.  
  267. function getEachElements(array, selector, key, type) {
  268. var newElementsArray = [],
  269. isValidSelector = typeof selector === 'string' && selector.trim() !== '';
  270.  
  271. CFL.each(array, function (currentElement) {
  272. while ( currentElement = currentElement[key] ) { // note: intentional assignment
  273. if (type > 0 ? currentElement.nodeType === type : true) {
  274. if ( isValidSelector === false || CFL(currentElement).filter(selector).exists ) {
  275. newElementsArray.push(currentElement);
  276. return;
  277. }
  278. }
  279. }
  280. });
  281.  
  282. return newElementsArray;
  283. }
  284.  
  285. // this will take
  286. function doElementOperationOnEach(args, op) {
  287. var newElementsArray = [], newElement,
  288. passedElements = CFL.create.apply(CFL, args);
  289.  
  290. if (this.exists) {
  291. if (CFL.typeOf(passedElements) === 'array') {
  292. this.each(function (thisElement) {
  293. CFL.each(passedElements, function (passedElement) {
  294. // clone the element
  295. var newElement = cloneElement(passedElement);
  296.  
  297. // add the new elements to an array
  298. newElementsArray.push(newElement);
  299.  
  300. // perform the passed operation on the element
  301. op(thisElement, newElement);
  302. });
  303. });
  304. } else {
  305. this.each(function (thisElement) {
  306. // clone the element
  307. var newElement = cloneElement(passedElements);
  308.  
  309. // add the new elements to an array
  310. newElementsArray.push(newElement);
  311.  
  312. // perform the passed operation on the element
  313. op(thisElement, newElement);
  314. });
  315. }
  316. }
  317.  
  318. return newElementsArray;
  319. }
  320.  
  321. // define CFL's prototype, aka CFL.fn
  322. CFL.fn = CFL.prototype = {
  323. isCFL : true,
  324. constructor : CFL,
  325. length : 0,
  326. version : version,
  327.  
  328. // similar to jQuery. CFL is just the init constructor
  329. init : function (selector, context) {
  330. var selectorStringValue = core.toString.call(selector),
  331. that = this,
  332. elems = [];
  333.  
  334. switch (typeof selector) {
  335. case 'string': { // -- STRING --
  336. if ( selector.match(rXpath) ) {
  337. // handle an XPath expression
  338. elems = CFL.xpath({expression : selector, type : 7, context : context});
  339. } else if ( selector.match(rHTML) ) {
  340. // reserved for html code creation
  341. // not sure if I want to implement it
  342. } else if ( selector.match(rSelector) ) {
  343. if (CFL.typeOf(context) === 'array') {
  344. // handle an array being passed as the context
  345. return that.find.call(context, selector);
  346. } else if (typeof context === 'string') {
  347. // handle a selector being passsed as the context
  348. context = CFL(context);
  349. if (context.exists) {
  350. return CFL(selector, context[0]);
  351. }
  352. } else if (context != null && context.isCFL === true && context.exists) {
  353. // handle a CFL object being passsed as the context
  354. return CFL( selector, context[0] );
  355. } else {
  356. // handle a regular element being passed as the context
  357. context = context != null && context.querySelectorAll ? context : document;
  358. elems = context.querySelectorAll(selector);
  359. }
  360. }
  361. break;
  362. }
  363. // ---------------------------------------------------
  364. case 'object': { // -- OBJECT --
  365. if (selector != null) {
  366. if (selector.isCFL === true) {
  367. // handle a CFL object
  368. return selector;
  369. } else if ( core.hasOwnProperty.call(selector, 'length') ) {
  370. // handle an array-like object
  371. elems = selector;
  372. } else if ( selectorStringValue.match(rElementObject) || selectorStringValue.match(rWindowObject) ) {
  373. // handle a single element
  374. elems = [selector];
  375. }
  376. }
  377. break;
  378. }
  379. // ---------------------------------------------------
  380. default: { // -- UNKNOWN --
  381. if ( selectorStringValue.match(rElementObject) || selectorStringValue.match(rWindowObject) ) {
  382. // handle elements that are typeof === 'function'
  383. // e.g., object, applet, embed
  384. elems = [selector];
  385. }
  386. }
  387. }
  388.  
  389. // define the length property of our object wrapper
  390. that.length = elems.length;
  391.  
  392. // bind the elements to array-like key:value pairs in our wrapper
  393. // e.g., this[0] ==> element
  394. CFL.each(elems, function (value, index) {
  395. that[index] = value;
  396. });
  397.  
  398. return that;
  399. },
  400.  
  401. // --- STARTING LINE FOR THE CFL WRAPPER METHODS
  402. add : function (selector, context) {
  403. var newElements = CFL(selector, context).raw(),
  404. allElements = core.concat.call(this.raw(), newElements);
  405. return CFL(allElements);
  406. },
  407.  
  408. addEvent : function (type, fn) {
  409. return this.each(function (thisElement) {
  410. CFL.addEvent(thisElement, type, fn);
  411. });
  412. },
  413.  
  414. after : function () {
  415. var newElementsArray = doElementOperationOnEach.call(this, CFL.toArray(arguments), function (baseElement, newElement) {
  416. var parent = baseElement.parentNode,
  417. next = baseElement.nextSibling;
  418.  
  419. if (parent) {
  420. if (next) {
  421. // add the newElement after the current element
  422. parent.insertBefore(newElement, next);
  423. } else {
  424. // nextSibling didn't exist. just append to its parent
  425. parent.appendChild(newElement);
  426. }
  427. }
  428. });
  429.  
  430. return CFL(newElementsArray);
  431. },
  432.  
  433. append : function () {
  434. var newElementsArray = doElementOperationOnEach.call(this, CFL.toArray(arguments), function (baseElement, newElement) {
  435. baseElement.appendChild(newElement);
  436. });
  437.  
  438. return CFL(newElementsArray);
  439. },
  440.  
  441. attribute : function (name, value) {
  442. var ret = '', valueIsValid = value != null;
  443.  
  444. if ( typeof name === 'string' && this.exists ) {
  445. this.each(function (elem) {
  446. if (valueIsValid) {
  447. elem.setAttribute(name, value);
  448. } else {
  449. ret += elem.getAttribute(name) || '';
  450. }
  451. });
  452. }
  453.  
  454. return valueIsValid ? this : ret;
  455. },
  456.  
  457. before : function () {
  458. var newElementsArray = doElementOperationOnEach.call(this, CFL.toArray(arguments), function (baseElement, newElement) {
  459. var parent = baseElement.parentNode;
  460.  
  461. // add the newElement before the current element
  462. if (parent) {
  463. parent.insertBefore(newElement, baseElement);
  464. }
  465. });
  466.  
  467. return CFL(newElementsArray);
  468. },
  469.  
  470. center : function () {
  471. return this.each(function (thisElement) {
  472. thisElement = CFL(thisElement);
  473. thisElement.css('position', 'fixed');
  474. thisElement.css('top', Math.floor( (window.innerHeight - thisElement.height) / 2 ) + 'px');
  475. thisElement.css('left', Math.floor( (window.innerWidth - thisElement.width) / 2 ) + 'px');
  476. });
  477. },
  478.  
  479. clone : function () {
  480. var clonedElements = core.map.call(this, cloneElement); // variable for clarity
  481. return CFL(clonedElements);
  482. },
  483.  
  484. css : function (name, value) {
  485. if (typeof name === 'string') {
  486. // convert the hyphenated string to camel-case
  487. name = toCamelCase(name);
  488.  
  489. if (typeof value === 'string') {
  490. return this.each(function (thisElement) {
  491. if (name in thisElement.style) {
  492. thisElement.style[name] = value;
  493. }
  494. });
  495. }
  496.  
  497. return core.map.call(this, pluck, 'style.' + name).join('');
  498. } else {
  499. return error('.css() was not passed a string for the first argument.');
  500. }
  501. },
  502.  
  503. each : function (fn, oThis) {
  504. if (this.exists) {
  505. CFL.each(this, fn, oThis);
  506. }
  507.  
  508. return this;
  509. },
  510.  
  511. get exists() {
  512. return this.length > 0 && this[0] != null;
  513. },
  514.  
  515. filter : function (selector) {
  516. var newElementsArray = [];
  517.  
  518. if (typeof selector === 'string') {
  519. this.each(function (thisElement) {
  520. if ( matchesSelector(thisElement, selector) ) {
  521. newElementsArray.push(thisElement);
  522. }
  523. });
  524. }
  525.  
  526. // returns an empty CFL object if no elements are matched
  527. return CFL(newElementsArray);
  528. },
  529.  
  530. find : function (selector) {
  531. var arrayOfMatchesArrays = core.map.call(this, function (thisElement) {
  532. var matches = thisElement.querySelectorAll(selector);
  533. return CFL.toArray(matches);
  534. });
  535. var singleArrayOfMatches = arrayOfMatchesArrays.length > 0 ?
  536. core.reduce.call(arrayOfMatchesArrays, function (a, b) {
  537. return core.concat.call(a, b);
  538. }) : [];
  539.  
  540. return CFL(singleArrayOfMatches);
  541. },
  542.  
  543. first : function () {
  544. return this.get(0);
  545. },
  546.  
  547. focus : function () {
  548. var firstElement;
  549.  
  550. if (this.exists) {
  551. firstElement = this[0];
  552. if (typeof firstElement.focus === 'function') {
  553. firstElement.focus();
  554. }
  555. }
  556. },
  557.  
  558. get : function (index) {
  559. index = index === 'first' ? 0 : index === 'last' ? -1 : parseInt(index, 10);
  560.  
  561. if ( !isNaN(index) ) {
  562. return CFL( index < 0 ? this[this.length + index] : this[index] );
  563. }
  564.  
  565. return CFL.toArray(this);
  566. },
  567.  
  568. get height() {
  569. var arrayOfElemHeights = core.map.call(this, pluck, 'offsetHeight');
  570. return core.reduce.call(arrayOfElemHeights, sum);
  571. },
  572.  
  573. has : function (selector) {
  574. var newElementsArray = [];
  575.  
  576. if ( typeof selector === 'string' && selector.match(rSelector) ) {
  577. this.each(function (thisElement) {
  578. if ( CFL(selector, thisElement).exists ) {
  579. newElementsArray.push(thisElement);
  580. }
  581. });
  582. }
  583.  
  584. return CFL(newElementsArray);
  585. },
  586.  
  587. hide : function () {
  588. return this.css('display', 'none');
  589. },
  590.  
  591. /*
  592. get inView(passedContainer) {
  593. var isInView = false;
  594.  
  595. this.each(function (thisElement) {
  596. var container = passedContainer || thisElement.parentNode;
  597. var visible = !!( (container.scrollTop + container.offsetHeight) >= thisElement.offsetTop &&
  598. (container.scrollTop - thisElement.offsetHeight) <= thisElement.offsetTop );
  599.  
  600. if (visible) {
  601. isInView = true;
  602. return 'stop';
  603. }
  604. });
  605.  
  606. return isInView;
  607. },
  608. */
  609.  
  610. is : function (selector) {
  611. for (var i = 0; i < this.length; i += 1) {
  612. if ( matchesSelector(this[i], selector) ) {
  613. return true;
  614. }
  615. }
  616.  
  617. return false;
  618. },
  619.  
  620. isnt : function (selector) {
  621. return !this.is(selector);
  622. },
  623.  
  624. last : function (selector) {
  625. return this.get(-1);
  626. },
  627.  
  628. next : function (selector) {
  629. return CFL( getEachElements(this, selector, 'nextSibling', 1) );
  630. },
  631.  
  632. not : function (selector) {
  633. var newElementsArray = [];
  634.  
  635. if ( typeof selector === 'string' && selector.match(rSelector) ) {
  636. this.each(function (thisElement) {
  637. if ( CFL(thisElement).isnt(selector) ) {
  638. newElementsArray.push(thisElement);
  639. }
  640. });
  641. }
  642.  
  643. return CFL(newElementsArray);
  644. },
  645.  
  646. parent : function (selector) {
  647. return CFL( getEachElements(this, selector, 'parentNode', 1) );
  648. },
  649.  
  650. prepend : function () {
  651. var newElementsArray = doElementOperationOnEach.call(this, CFL.toArray(arguments), function (baseElement, newElement) {
  652. var firstChild = baseElement.firstChild;
  653.  
  654. if (firstChild) {
  655. baseElement.insertBefore(newElement, firstChild);
  656. }
  657. });
  658.  
  659. return CFL(newElementsArray);
  660. },
  661.  
  662. prev : function (selector) {
  663. return CFL( getEachElements(this, selector, 'previousSibling', 1) );
  664. },
  665.  
  666. prop : function (name, value) {
  667. var valueIsValid = value != null, ret;
  668.  
  669. if (typeof name === 'string' && this.exists) {
  670. this.each(function (thisElement) {
  671. if (valueIsValid) {
  672. thisElement[name] = value;
  673. } else {
  674. if (typeof ret === 'undefined') {
  675. ret = thisElement[name];
  676. } else {
  677. ret += thisElement[name];
  678. }
  679. }
  680. });
  681. }
  682.  
  683. return valueIsValid ? this : ret;
  684. },
  685.  
  686. raw : function () {
  687. return core.slice.call(this, 0);
  688. },
  689.  
  690. remove : function () {
  691. return this.each(function (element) {
  692. var parent = element.parentNode;
  693.  
  694. if (element && parent) {
  695. parent.removeChild(element);
  696. }
  697. });
  698. },
  699.  
  700. removeAttribute : function (attributeName) {
  701. if (typeof attributeName === 'string') {
  702. return this.each(function (thisElement) {
  703. thisElement.removeAttribute(attributeName);
  704. });
  705. } else {
  706. return error('.removeAttribute() was not passed a string.');
  707. }
  708. },
  709.  
  710. removeEvent : function (type) {
  711. if (typeof type === 'string') {
  712. return this.each(function (thisElement) {
  713. CFL.removeEvent(thisElement, type);
  714. });
  715. } else {
  716. return error('.removeEvent() was not passed a string.');
  717. }
  718. },
  719.  
  720. replace : function () {
  721. var newElementsArray = doElementOperationOnEach.call(this, CFL.toArray(arguments), function (baseElement, newElement) {
  722. var parent = baseElement.parentNode;
  723.  
  724. if (parent) {
  725. parent.replaceChild(newElement, baseElement);
  726. }
  727. });
  728.  
  729. return CFL(newElementsArray);
  730. },
  731.  
  732. show : function (value) {
  733. value = typeof value === 'string' ? value : 'inline';
  734. return this.css('display', value);
  735. },
  736.  
  737. text : function (passedText, append) {
  738. // convert a number to a string
  739. if ( typeof passedText === 'number' && !isNaN(passedText) && isFinite(passedText) ) {
  740. passedText += '';
  741. }
  742.  
  743. // handle setting text
  744. if (typeof passedText === 'string') {
  745. if (append !== true) {
  746. this.each(function (thisElement) {
  747. CFL('.//text()', thisElement).each(function (textNode) {
  748. textNode.data = '';
  749. });
  750. });
  751. }
  752.  
  753. this.append('text', passedText);
  754. return this;
  755. }
  756.  
  757. // handle getting text
  758. return core.reduce.call(this, function (curValue, nextElement) {
  759. return curValue + nextElement.textContent;
  760. }, '');
  761. },
  762.  
  763. toggle : function () {
  764. return this.each(function (thisElement) {
  765. thisElement = CFL(thisElement);
  766.  
  767. if (thisElement.visible) {
  768. thisElement.hide();
  769. } else {
  770. thisElement.show();
  771. }
  772. });
  773. },
  774.  
  775. value : function (passedValue) {
  776. var elem = this[0],
  777. tagName = elem && elem.tagName || '',
  778. selectedOptions = [],
  779. rInputTypeBlacklist = /button|checkbox|file|image|radio|reset|submit/,
  780. passedValueType = CFL.typeOf(passedValue);
  781.  
  782. if (passedValue == null) {
  783. // no arguments were passed, return a value
  784. if (tagName === 'SELECT') {
  785. if ( elem.hasAttribute('multiple') ) {
  786. CFL.each(elem.options, function (thisOption) {
  787. if (thisOption.selected) {
  788. selectedOptions.push(thisOption.value);
  789. }
  790. });
  791.  
  792. return selectedOptions;
  793. } else {
  794. return elem.options[elem.selectedIndex].value;
  795. }
  796. } else if ( tagName === 'INPUT' && !elem.type.match(rInputTypeBlacklist) ) {
  797. return elem.value;
  798. }
  799. if (tagName === 'TEXTAREA') {
  800. return elem.value;
  801. }
  802. } else {
  803. // an argument was passed, set the value on each element
  804. return this.each(function (thisElement) {
  805. var tagName = thisElement.tagName;
  806.  
  807. if (tagName === 'SELECT') {
  808. if (thisElement.hasAttribute('multiple') && passedValueType === 'array') {
  809. CFL.each(thisElement.options, function (thisOption) {
  810. CFL.each(passedValue, function (thisPassedValue) {
  811. if (thisOption.value == thisPassedValue) {
  812. thisOption.selected = true;
  813. return 'stop';
  814. } else {
  815. thisOption.selected = false;
  816. }
  817. });
  818. });
  819. } else {
  820. CFL.each(thisElement.options, function (thisOption) {
  821. thisOption.selected = thisOption.value == passedValue;
  822. });
  823. }
  824. } else if (tagName === 'INPUT') {
  825. if ( !thisElement.type.match(rInputTypeBlacklist) ) {
  826. thisElement.value = passedValue;
  827. } else if (thisElement.type === 'checkbox' || thisElement.type === 'radio') {
  828. if (passedValueType === 'array') {
  829. CFL.each(passedValue, function (thisPassedValue) {
  830. if (thisElement.value == thisPassedValue) {
  831. thisElement.checked = true;
  832. return 'stop';
  833. } else {
  834. thisElement.checked = false;
  835. }
  836. });
  837. } else if (thisElement.value == passedValue) {
  838. thisElement.checked = true;
  839. }
  840. }
  841. } else if (tagName === 'TEXTAREA') {
  842. thisElement.value = passedValue;
  843. }
  844. });
  845. }
  846.  
  847. return null;
  848. },
  849.  
  850. get visible() {
  851. return Math.max(this.width, this.height) > 0;
  852. },
  853.  
  854. get width() {
  855. var arrayOfElemHeights = core.map.call(this, pluck, 'offsetWidth');
  856. return core.reduce.call(arrayOfElemHeights, sum);
  857. },
  858. };
  859.  
  860. // give the init function the CFL prototype for later instantiation
  861. CFL.fn.init.prototype = CFL.fn;
  862.  
  863. // extend method. can extend any object it's run upon
  864. CFL.fn.extend = CFL.extend = function (obj) {
  865. var name, copy;
  866.  
  867. for (name in obj) {
  868. copy = obj[name];
  869.  
  870. if ( !core.hasOwnProperty.call(this, name) && typeof copy !== 'undefined' ) {
  871. this[name] = copy;
  872. }
  873. }
  874. };
  875.  
  876. // --- STARTLING LINE FOR THE DIRECT CFL METHODS
  877. CFL.extend({
  878. addEvent : function addEvent(thisElement, type, fn) {
  879. if (thisElement != null && typeof type === 'string' && typeof fn === 'function') {
  880. if (typeof thisElement.addEventListener === 'function') {
  881. thisElement.addEventListener(type, fn, false);
  882. } else if (typeof thisElement.attachEvent === 'function') {
  883. type = 'on' + type;
  884. thisElement.attachEvent(type, fn);
  885. } else {
  886. return;
  887. }
  888.  
  889. handlers.add(thisElement, type, fn);
  890. }
  891. },
  892.  
  893. addScript : function addScript(contents, id, node) {
  894. var newElement = document.createElement('script');
  895. newElement.id = id || ( 'cfl-script-' + CFL.random(999) );
  896. newElement.innerHTML = contents;
  897.  
  898. node = node || document.head || document.querySelector('html > head');
  899. node.appendChild(newElement);
  900.  
  901. return {
  902. remove : function () {
  903. node.removeChild(newElement);
  904. }
  905. };
  906. },
  907.  
  908. addStyle : function addStyle(css, id, node) {
  909. id = id || ( 'cfl-style-' + CFL.random(999) );
  910. node = node || document.head || document.querySelector('html > head');
  911. if (node) {
  912. node.appendChild(
  913. CFL.create('style', {id : id, type : 'text/css'}, [ CFL.create('text', css) ] )
  914. );
  915. }
  916. },
  917.  
  918. alias : function alias(newAlias) {
  919. if (typeof newAlias === 'string' && newAlias.match(rValidVarname) && typeof window[newAlias] === 'undefined') {
  920. window[newAlias] = CFL;
  921. }
  922. },
  923.  
  924. clearInterval : function clearInterval(index) {
  925. if (typeof index === 'number' && index < intervals.length) {
  926. window.clearTimeout( intervals[index] );
  927. intervals[index] = null;
  928. }
  929. },
  930.  
  931. create : function create(elementName, descObj, kidsArray) {
  932. var argsLength = arguments.length,
  933. typeValue, prop, val, HTMLholder, ret, i;
  934.  
  935. if (argsLength === 2 && elementName === 'text' && typeof descObj === 'string') {
  936. // handle text node creation
  937. return document.createTextNode(descObj);
  938. } else if ( argsLength === 1 && typeof elementName === 'string' && elementName.match(rHTML) ) {
  939. // handle HTML strings
  940.  
  941. // take the HTML string and put it inside a div
  942. HTMLholder = document.createElement('div');
  943. HTMLholder.innerHTML = elementName;
  944.  
  945. // add each childNode to an array to return
  946. ret = [];
  947. ret.push.apply(ret, HTMLholder.childNodes);
  948. return ret.length > 0 ? (ret.length === 1 ? ret[0] : ret) : null;
  949. } else if (argsLength > 1 && typeof elementName === 'string' && typeof descObj === 'object') {
  950. // handle the normal element name and descriptor object
  951. ret = document.createElement(elementName + '');
  952.  
  953. for (prop in descObj) {
  954. if ( core.hasOwnProperty.call(descObj, prop) ) {
  955. val = descObj[prop];
  956. if (prop.indexOf('on') === 0 && typeof val === 'function') {
  957. CFL.addEvent(ret, prop.substring(2), val);
  958. } else if ( prop !== 'style' && prop !== 'class' && prop in ret && typeof ret[prop] !== 'undefined' ) {
  959. ret[prop] = val;
  960. } else {
  961. ret.setAttribute(prop, val);
  962. }
  963. }
  964. }
  965.  
  966. if (CFL.typeOf(kidsArray) === 'array') {
  967. CFL.each(kidsArray, function (kid) {
  968. var val, item, i;
  969.  
  970. if (typeof kid === 'string') {
  971. val = CFL.create(kid)
  972.  
  973. if (CFL.typeOf(val) === 'array') {
  974. for (i = 0; i < val.length; i += 1) {
  975. ret.appendChild( val[i] );
  976. }
  977. } else if (CFL.typeOf(kid) === 'element') {
  978. ret.appendChild(kid);
  979. }
  980. } else if (CFL.typeOf(kid) === 'element') {
  981. ret.appendChild(kid);
  982. }
  983. });
  984. }
  985.  
  986. return ret;
  987. } else if (argsLength === 1 && CFL.typeOf(elementName) === 'element') {
  988. // handle an element
  989. return elementName;
  990. }
  991. },
  992.  
  993. each : function each(passedArray, fn, oThis) {
  994. var isOthisUndefined = typeof oThis !== 'undefined',
  995. index, len, otherThis, value;
  996.  
  997. for (index = 0; index < passedArray.length; index += 1) {
  998. value = passedArray[index];
  999. otherThis = isOthisUndefined ? oThis : value;
  1000. if (fn.call(otherThis, value, index, passedArray) === 'stop') {
  1001. break;
  1002. }
  1003. }
  1004. },
  1005.  
  1006. loop : function loop(maxIterations, fn) {
  1007. var args = CFL.toArray(arguments), i;
  1008.  
  1009. if (typeof maxIterations === 'number' && maxIterations > 0 && typeof fn === 'function') {
  1010. args = args.slice(2);
  1011. for (i = 0; i < maxIterations; i += 1) {
  1012. fn.apply(null, args);
  1013. }
  1014. }
  1015. },
  1016.  
  1017. random : function random(maxInteger, minInteger) {
  1018. var rand = -1;
  1019.  
  1020. while (rand < 0 || rand > maxInteger || rand < minInteger) {
  1021. rand = Math.floor( Math.random() * maxInteger ) + Math.round( Math.random() );
  1022. }
  1023.  
  1024. return rand;
  1025. },
  1026.  
  1027. removeEvent : function removeEvent(thisElement, type) {
  1028. CFL.each(handlers.get(thisElement, type), function (thisEventObj) {
  1029. if (typeof thisElement.removeEventListener === 'function') {
  1030. thisEventObj.element.removeEventListener(thisEventObj.type, thisEventObj.fn, false);
  1031. } else if (typeof thisElement.detachEvent === 'function') {
  1032. type = 'on' + type;
  1033. thisEventObj.element.detachEvent(thisEventObj.type, thisEventObj.fn);
  1034. }
  1035.  
  1036. handlers.remove(thisElement, type);
  1037. });
  1038. },
  1039.  
  1040. runAt : function runAt(state, func, oThis) {
  1041. var args = CFL.toArray(arguments), intv,
  1042.  
  1043. // compose a list of the 4 states, to use .indexOf() upon later
  1044. states = ['uninitialized', 'loading', 'interactive', 'complete'],
  1045.  
  1046. // in-case they pass [start/end] instead of [loading/complete]
  1047. state = state.replace('start', 'loading').replace('end', 'complete');
  1048.  
  1049. // this will run their function with the specified arguments, if any,
  1050. // and a custom 'this' value, if specified
  1051. function runFunc() {
  1052. func.apply( oThis, args.slice(3) );
  1053. }
  1054.  
  1055. // this will run on each state change if the specified state is
  1056. // not achieved yet. it will run their function when it is achieved
  1057. function checkState() {
  1058. if (document.readyState === state) {
  1059. runFunc();
  1060. CFL.clearInterval(intv);
  1061. }
  1062. }
  1063.  
  1064. if ( core.arr_indexOf.call(states, state) <= core.arr_indexOf.call(states, document.readyState) ) {
  1065. // we are at, or have missed, our desired state
  1066. // run the specified function
  1067. runFunc();
  1068. } else {
  1069. intv = CFL.setInterval(checkState, 200);
  1070. }
  1071. },
  1072.  
  1073. setInterval : function setInterval(func, delay) {
  1074. var index = intervals.length,
  1075. delay_orig = delay,
  1076. count = 1, startTime;
  1077.  
  1078. function doRe(func, delay) {
  1079. return window.setTimeout(function () {
  1080. // drift accomodation
  1081. var difference = ( new Date().getTime() ) - startTime,
  1082. correctTime = delay_orig * count,
  1083. drift = difference - correctTime;
  1084.  
  1085. // execute the function before setting a new timeout
  1086. func.call(null);
  1087.  
  1088. // fix for when a timeout takes longer than double the original delay time to execute
  1089. if (drift > delay_orig) {
  1090. drift = delay_orig;
  1091. }
  1092.  
  1093. // save the reference of the new timeout in our 'intervals' stack
  1094. if (intervals[index] !== null) {
  1095. intervals[index] = doRe(func, delay_orig - drift);
  1096. }
  1097.  
  1098. count += 1;
  1099. }, delay);
  1100. }
  1101.  
  1102. startTime = new Date().getTime();
  1103. intervals[index] = doRe(func, delay_orig);
  1104.  
  1105. return index;
  1106. },
  1107.  
  1108. toArray : function toArray(arr) {
  1109. var newArr = [], // new array to store the values into
  1110. len = arr.length || arr.snapshotLength,
  1111. item, i;
  1112.  
  1113. if (typeof len === 'number' && len > 0) {
  1114. if (typeof arr.snapshotItem === 'function') {
  1115. for (i = 0; ( item = arr.snapshotItem(i) ); i += 1) {
  1116. newArr.push(item);
  1117. }
  1118. } else {
  1119. // if the specified 'list' is array-like, use slice on it
  1120. // to convert it to an array
  1121. newArr = core.slice.call(arr, 0);
  1122. }
  1123. }
  1124.  
  1125. return newArr;
  1126. },
  1127.  
  1128. toString : function toString(item) {
  1129. var key, value, values = [];
  1130.  
  1131. function stringifyValue(val) {
  1132. var typeOfVal = CFL.typeOf(val),
  1133. toStringValue = core.toString.call(val);
  1134.  
  1135. if (typeOfVal === 'null' || typeOfVal === 'undefined') {
  1136. val = typeOfVal;
  1137. } else if (typeof val === 'string') {
  1138. if (val.length > 15) { // truncate strings longer than 15 characters
  1139. val = '"' + val.substring(0, 12) + '"...';
  1140. } else {
  1141. val = '"' + val + '"';
  1142. }
  1143. } else if (typeOfVal === 'function') {
  1144. val = val.toString().substring(0, 20);
  1145. } else if (typeOfVal !== 'number' && typeOfVal !== 'boolean') {
  1146. val = toStringValue;
  1147. }
  1148.  
  1149. return val;
  1150. }
  1151.  
  1152. switch( CFL.typeOf(item) ) {
  1153. case 'object': {
  1154. for (key in item) {
  1155. if ( item.hasOwnProperty(key) ) {
  1156. value = stringifyValue( item[key] );
  1157. values.push( '"' + key + '" : ' + value );
  1158. }
  1159. }
  1160. return '{\n ' + values.join(',\n ') + '\n}';
  1161. }
  1162. // --------------------------------------
  1163. case 'array': {
  1164. item = core.map.call(item, function (thisValue) {
  1165. return stringifyValue(thisValue);
  1166. });
  1167. return '[\n ' + item.join(',\n ') + '\n]';
  1168. }
  1169. // --------------------------------------
  1170. case 'string': {
  1171. return '"' + item + '"';
  1172. }
  1173. // --------------------------------------
  1174. case 'number': {
  1175. item = parseInt(item, 10);
  1176. if ( isNaN(item) ) { // no ternary operator, for clarity
  1177. return 'NaN';
  1178. } else {
  1179. return item.toString();
  1180. }
  1181. }
  1182. // --------------------------------------
  1183. case 'regexp': {
  1184. if (item.toString().length <= 20) {
  1185. item.toString();
  1186. } else {
  1187. return '[object RegExp]';
  1188. }
  1189. }
  1190. // --------------------------------------
  1191. case 'function': case 'boolean': {
  1192. return item.toString();
  1193. }
  1194. // --------------------------------------
  1195. case 'null': {
  1196. return 'null';
  1197. }
  1198. // --------------------------------------
  1199. case 'undefined': {
  1200. return 'undefined';
  1201. }
  1202. // --------------------------------------
  1203. default: {
  1204. return core.toString.call(item);
  1205. }
  1206. }
  1207. },
  1208.  
  1209. // typeOf by Douglas Crockford. modified by CodeFelony
  1210. typeOf : function typeOf(value) {
  1211. var s = typeof value,
  1212. ostr = core.toString.call(value);
  1213.  
  1214. if (s === 'object' || s === 'function') {
  1215. if (value) {
  1216. if (ostr === '[object Array]') {
  1217. s = 'array';
  1218. } else if ( ostr === '[object Text]' || ostr.match(rElementObject) ) {
  1219. s = 'element';
  1220. } else if (ostr === '[object HTMLCollection]') {
  1221. s = 'collection';
  1222. } else if (ostr === '[object NodeList]') {
  1223. s = 'nodelist';
  1224. } else if (ostr === '[object Arguments]') {
  1225. s = 'arguments';
  1226. } else if (ostr === '[object RegExp]') {
  1227. s = 'regexp';
  1228. }
  1229. } else {
  1230. s = 'null';
  1231. }
  1232. }
  1233. return s;
  1234. },
  1235.  
  1236. waitFor : function waitFor(info) {
  1237. var verifier = function () { return true; },
  1238. done = info ? info.done : null,
  1239. i, selector, context, waitForInterval;
  1240.  
  1241. if (info == null || typeof done !== 'function') { return; }
  1242.  
  1243. switch ( CFL.typeOf(info.selector) ) {
  1244. case 'string': case 'element': case 'array': {
  1245. selector = info.selector;
  1246. break;
  1247. }
  1248. default: {
  1249. return error('Invalid selector passed to CFL.waitFor()');
  1250. }
  1251. }
  1252.  
  1253. switch ( CFL.typeOf(info.context) ) {
  1254. case 'string': case 'element': case 'array': {
  1255. context = info.context;
  1256. }
  1257. }
  1258.  
  1259. if (typeof info.verifier === 'function' && info.verifier.toString().indexOf('return ') !== -1) {
  1260. verifier = info.verifier;
  1261. }
  1262.  
  1263. function clear() {
  1264. CFL.clearInterval(waitForInterval);
  1265. }
  1266.  
  1267. function check() {
  1268. var elem = CFL(selector, context);
  1269.  
  1270. if (elem.exists && verifier(elem) === true) {
  1271. done(elem);
  1272. return clear();
  1273. }
  1274.  
  1275. if (i >= 150) { // check for 30 seconds max
  1276. return clear();
  1277. }
  1278.  
  1279. i += 1;
  1280. }
  1281.  
  1282. waitForInterval = CFL.setInterval(check, 200);
  1283. },
  1284.  
  1285. xpath : function xpath(obj) {
  1286. var type = obj.type || 7,
  1287. types = {
  1288. '1' : 'numberValue',
  1289. '2' : 'stringValue',
  1290. '3' : 'booleanValue',
  1291. '8' : 'singleNodeValue',
  1292. '9' : 'singleNodeValue'
  1293. },
  1294. expression = obj.expression,
  1295. context = obj.context || document,
  1296. doc = document, xp;
  1297.  
  1298. if (typeof context.evaluate === 'function') {
  1299. doc = context;
  1300. } else if (typeof context.ownerDocument.evaluate === 'function') {
  1301. doc = context.ownerDocument;
  1302. }
  1303.  
  1304. xp = doc.evaluate(expression, context, null, type, null);
  1305.  
  1306. if (!expression) {
  1307. error('An expression must be supplied for CFL.xpath()');
  1308. return null;
  1309. }
  1310.  
  1311. if ( types[type] ) {
  1312. return xp[ types[ type ] ];
  1313. } else {
  1314. return CFL.toArray(xp);
  1315. }
  1316. }
  1317. });
  1318.  
  1319. // assign CFL to the window object
  1320. if (typeof window.CFL !== 'function') {
  1321. // if it doesn't exist, just add it
  1322. window.CFL = CFL;
  1323. window._J = CFL;
  1324. } else if (window.CFL.fn && window.CFL.fn.version) {
  1325. // if it already exists, only replace it with a newer, yet
  1326. // backwards compatible version (check for same major version)
  1327. if ( window.CFL.fn.version.substring( 0, window.CFL.fn.version.indexOf('.') )
  1328. === version.substring( 0, version.indexOf('.') ) ) {
  1329. window.CFL = CFL;
  1330. window._J = CFL;
  1331. }
  1332. }
  1333.  
  1334. // just for testing purposes
  1335. // unsafeWindow.CFL = unsafeWindow._J = CFL;
  1336.  
  1337. }(window));
  1338.  
  1339.  
  1340.  
  1341. // CFL test button
  1342. // use it to test code on user click (non-automatic)
  1343. /*
  1344. (function () {
  1345. var mo = new MutationObserver(function (mutations) {
  1346. mutations.forEach(function (mutation) {
  1347. var target = mutation.target;
  1348.  
  1349. if (mutation.attributeName === 'value' && target.value !== 'Run CFL test') {
  1350. target.value = 'Run CFL test';
  1351. }
  1352. });
  1353. });
  1354.  
  1355. CFL(document.body).append(
  1356. 'input',
  1357. {
  1358. id : 'cfl_user_test',
  1359. type : 'button',
  1360. value : 'Run CFL test',
  1361. style : 'display: block; position: fixed; top: 4px; right: 4px; z-index: 999999; padding: 2px 14px; font-size: 11pt; font-family: Arial, Verdana;',
  1362. onclick : function () {
  1363.  
  1364. // ---- ENTER ONCLICK CODE HERE ----
  1365. window.setTimeout(function () {
  1366. CFL(document.body).append('<div id="waitForTest">I\'m a CFL.waitFor() test DIV!</div>');
  1367. }, 1500);
  1368.  
  1369. CFL.waitFor({
  1370. selector : '#waitForTest',
  1371. done : function (elem) {
  1372. alert('#waitForTest is loaded!');
  1373. }
  1374. });
  1375. // ---------------------------------
  1376. }
  1377. }
  1378. );
  1379.  
  1380. mo.observe( CFL('#cfl_user_test')[0], { attributes : true } );
  1381. }());
  1382. */
  1383.  

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址