My Function library

enter something useful

当前为 2016-05-29 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/9160/128176/My%20Function%20library.js

  1. "use strict";
  2. //// ==UserScript==
  3. // @name My Function library
  4. // @namespace http://use.i.E.your.homepage/
  5. // @version 0.40
  6. // @description enter something useful
  7. // @grant GM_getValue
  8. // @grant GM_setValue
  9. // @grant GM_deleteValue
  10. // @run-at document-start
  11.  
  12. // @created 2015-04-06
  13. // @released 2014-00-00
  14. // @updated 2014-00-00
  15. // @history @version 0.25 - first version: public@released - 2015-04-12
  16. // @history @version 0.30 - Second version: public@released - 2015-12-10
  17. // @history @version 0.35 - Second version: public@released - 2016-03-04
  18. // @history @version 0.40 - Second version: public@released - 2016-05-29
  19. // @compatible Greasemonkey, Tampermonkey
  20. // @license GNU GPL v3 (http://www.gnu.org/copyleft/gpl.html)
  21. // @copyright 2014+, Magnus Fohlström
  22. // ==/UserScript==
  23.  
  24. /*global $, jQuery*/
  25. /*jshint -W014, -W030, -W082*/
  26. // -W014, laxbreak, Bad line breaking before '+'
  27. // -W030, Expected assignment or function call instead saw an expression
  28. // -W082, a function declaration inside a block statement
  29.  
  30. /*
  31. $("li").not(function() {
  32. // returns true for those elements with at least one span as child element
  33. return $(this).children('span').length > 0
  34. }).each(function() { /* ... })
  35. */
  36. //noinspection JSUnresolvedFunction,JSUnresolvedVariable,BadExpressionStatementJS
  37. performance;
  38.  
  39. window.onerror = function (errorMsg, url, lineNumber, column, errorObj) {
  40. console.debug('Error: ' + errorMsg + '\nScript: ' + url + '\nLine: ' + lineNumber
  41. + '\nColumn: ' + column + '\nStackTrace: ' + errorObj);
  42. };
  43. /**
  44. * @namespace waitUntilExists_Intervals
  45. */
  46. $.fn.waitUntilExists = function (handler, shouldRunHandlerOnce, isChild){
  47. var found = 'found',
  48. $this = $(this.selector),
  49. $elements = $this.not(function () { return $(this).data(found); }).each(handler).data(found, true);
  50. if( !isChild ) {
  51. (window.waitUntilExists_Intervals = window.waitUntilExists_Intervals || {})[this.selector] =
  52. window.setInterval(function () {
  53. $this.waitUntilExists(
  54. handler, shouldRunHandlerOnce, true);
  55. }, 500);
  56. }
  57. else if (shouldRunHandlerOnce && $elements.length){
  58. window.clearInterval(window.waitUntilExists_Intervals[this.selector]);
  59. }
  60. return $this;
  61. };
  62.  
  63. $.extend( $.easing,{
  64. easeOutBounceSmall : function(x, t, b, c, d) {
  65. var ts=(t/=d)*t;
  66. var tc=ts*t;
  67. return b+c*(-16.195*tc*ts + 49.935*ts*ts + -53.785*tc + 21.795*ts + -0.75*t);
  68. },
  69. easeOutSmoothBounce : function(x, t, b, c, d) {
  70. var ts=(t/=d)*t;
  71. var tc=ts*t;
  72. return b+c*(-19.4293*tc*ts + 53.3838*ts*ts + -49.8485*tc + 15.8081*ts + 1.08586*t);
  73. }
  74. });
  75.  
  76. $.extend( $.fn, {
  77. // Name of our method & one argument (the parent selector)
  78. /**
  79. * Suppress all rules containing "unused" in this
  80. * class
  81. *
  82. * @SuppressWarnings("unused")
  83. */
  84. //noinspection JSUnusedProperty
  85. within: function( pSelector ) {
  86. // Returns a subset of items using jQuery.filter
  87. return this.filter(function(){
  88. // Return truthy/falsey based on presence in parent
  89. return $(this).closest( pSelector ).length;
  90. });
  91. /* Example
  92. $("li").within(".x").css("background", "red");
  93.  
  94. This selects all list items on the document, and then filters to only
  95. those that have .x as an ancestor. Because this uses jQuery internally,
  96. you could pass in a more complicated selector:
  97.  
  98. $("li").within(".x, .y").css("background", "red");
  99.  
  100. http://stackoverflow.com/questions/2389540/jquery-hasparent
  101. http://stackoverflow.com/a/2389549
  102. */
  103. }
  104. });
  105.  
  106. $.fn.extend({
  107. exists : function () {
  108. return !!this.length;
  109. },
  110. Exists : function ( callback ) {
  111. var self = this;
  112. var wrapper = (function(){
  113. function notExists(){}
  114. //noinspection JSPotentiallyInvalidConstructorUsage
  115. notExists.prototype.ExistsNot = function( fallback ){
  116. !self.length && fallback.call(); };
  117. //noinspection JSPotentiallyInvalidConstructorUsage
  118. return new notExists;
  119. })();
  120. self.length && callback.call();
  121. return wrapper;
  122.  
  123. /* And now i can write code like this -
  124. $("#elem").Exists(function(){
  125. alert ("it exists");
  126. }).ExistsNot(function(){
  127. alert ("it doesn't exist");
  128. });
  129. */
  130. },
  131. ifExists : function ( fn ) {
  132. this.length && fn( this );
  133. /*
  134. $("#element").ifExists( function( $this ){
  135. $this.addClass('someClass').animate({marginTop:20},function(){alert('ok')});
  136. });
  137. */
  138. },
  139. swapClass : function ( replace, newClass) {
  140. this.className.replace(replace, newClass);
  141. },
  142. toggleClasses : function ( add, remove, if_none) {
  143. var $this = $(this.selector);
  144. if_none !== undefined && !$this.hasClass(add) && !$this.hasClass(remove) && $this.addClass(if_none);
  145. $this.addClass(add).removeClass(remove);
  146. },
  147. refreshElement : function ( speed, parentBoolean ) {
  148. var $elem = parentBoolean ? this.parent() : this, data = $elem.html();
  149. $elem.empty().html( data ).fadeIn( speed );
  150. },
  151. hasId : function ( id ) {
  152. return id === this.attr('id');
  153. },
  154. hasClasses : function ( classes, any ) {
  155. classes = classes.split( classes.inElem(',') ? ',' : ' ' );
  156. var check = 0, i = 0;
  157. for ( i; i < classes.length; i++ ) {
  158. this.hasClass( classes[ i ] ) && check++;
  159. if ( any !== undefined && check !== 0 ) return true;
  160. }
  161. return check === classes.length;
  162. },
  163. hasNoChildren : function ( selection ) {
  164. return $( this ).filter( function(){
  165. return $( this ).children( selection ).length === 0;
  166. });
  167. },
  168. /* hasParent : function( parentSelection ){
  169. return parentSelection.inElem('#')
  170. ? this.parent().hasId( parentSelection.split('#').shift() )
  171. : this.parent().hasClass( parentSelection.split('.').shift() );
  172. },
  173. */
  174. hasAncestor : function ( Ancestor ) {
  175. return this.filter(function() {
  176. return !!$( this ).closest( Ancestor ).length;
  177. });
  178. //$('.element').hasAncestor('.container').myAction();
  179. },
  180. hasParent : function ( selection ) {
  181. return !!$( this ).parent( selection ).length
  182. },
  183. hasParents : function ( selection ) {
  184. return !!$( this ).parents(e).length
  185. },
  186. hasQuery : function ( query ) {
  187. return d.querySelector(query).length;
  188. },
  189. hasAttr : function ( name, val ) {
  190. var thisAttr = $( this ).attr( name );
  191. thisAttr =
  192. val !== undefined
  193. ? thisAttr === val
  194. : thisAttr;
  195. return ( typeof thisAttr !== "undefined" && thisAttr !== false && thisAttr !== null );
  196.  
  197. //return val !== undefined
  198. // ? attrName === val
  199. // : typeof( attrName ) !== 'undefined'; //$( this )[0].hasAttribute( name );
  200. },
  201. isTag : function ( tag ) {
  202. var e = this[0] || $('<undefined/>');
  203. //noinspection JSValidateTypes
  204. return e.nodeName !== undefined && e.nodeName.toLowerCase() === tag.toLowerCase();
  205. },
  206. isNode : function ( node ) {
  207. var e = this[0] || $('<undefined/>');
  208. //noinspection JSValidateTypes
  209. return e.nodeName !== undefined && e.nodeName.toLowerCase() === node.toLowerCase();
  210. },
  211. searchAttr : function ( search, type, chkLen ) { //bool name value length or 1 2 3 4
  212. var Attributes = this[0].attributes;
  213. c.i('Attributes', Attributes);
  214. if ( arguments.length === 0 ) {
  215. var obj = {};
  216. $.each( Attributes, function() {
  217. this.specified && ( obj[ this.name ] = this.value );
  218. });
  219. return obj;
  220. } else if( search != undefined ) {
  221. var name = '', val = '';
  222. //noinspection FunctionWithInconsistentReturnsJS
  223. $.each( Attributes, function() {
  224. if( this.specified && type == 'length' ) {
  225. if( this.name.length > chkLen ) {
  226. name = this.name;
  227. return false;
  228. }
  229. }
  230. else if( this.specified && this.name.inElem( search ) ) {
  231. name = this.name;
  232. val = this.value;
  233. return false;
  234. }
  235. });
  236. return ( type == 'bool' || type == 1 ) ? name.length ? true : false :
  237. ( type == 'name' || type == 2 ) ? name :
  238. ( type == 'value' || type == 3 ) ? val :
  239. ( type == 'length' || type == 4 ) && name;
  240. }
  241. },
  242. findClass : function ( Class ) {
  243. return this.find('.' + Class)
  244. },
  245. href : function ( newURL ) {
  246. return arguments.length === 0 ? this.attr('href') : this.attr('href', newURL);
  247. },
  248. src : function ( newSRC ) {
  249. return arguments.length === 0 ? this.attr('src') : this.attr('src', newSRC);
  250. },
  251. equals : function ( compareTo ) {
  252. if (!compareTo || this.length != compareTo.length)
  253. return false;
  254.  
  255. for (var i = 0; i < this.length; ++i) {
  256. if (this[i] !== compareTo[i])
  257. return false;
  258. }
  259. return true;
  260. },
  261. justText : function ( newText, prepend ) {
  262. var $children = null,
  263. placement = prepend === undefined ? 'prepend':'append';
  264. if ( newText ) {
  265. $children = $( this )
  266. .children()
  267. .clone();
  268. $( this )
  269. .children()
  270. .remove()
  271. .end()
  272. .text( newText )
  273. [ placement ]( $children );
  274. return $(this);
  275. }
  276. else {
  277. return $.trim( $( this )
  278. .clone()
  279. .children()
  280. .remove()
  281. .end()
  282. .text());
  283. }
  284. },
  285. uncomment : function ( recurse ) {
  286. <!-- hidden --> // this will reveal, whats inside. In this case it will bi the word hidden
  287. $( this ).contents().each(function() {
  288. if ( recurse && this.hasChildNodes() ) {
  289. $( this ).uncomment(recurse);
  290. } else if ( this.nodeType == 8 ) {
  291. // Need to "evaluate" the HTML content,
  292. // otherwise simple text won't replace
  293. var e = $('<span>' + this.nodeValue + '</span>');
  294. $( this ).replaceWith( e.contents() );
  295. }
  296. });
  297. // $('#uncomment').uncomment( true );
  298. // http://stackoverflow.com/a/22439787
  299. },
  300. getComment : function ( getValue ) {
  301. var COMMENT_NODE = this.contents().filter(function(){
  302. return this.nodeType == Node.COMMENT_NODE;
  303. });
  304. return getValue ?
  305. COMMENT_NODE.each(function(){
  306. return $( this ).nodeValue.str2html();
  307. })
  308. : COMMENT_NODE;
  309. },
  310. hasEvent : function ( event ) {
  311. var eventHandlerType;
  312. $( this ).on( event, clickEventHandler ).triggerHandler( event );
  313. function clickEventHandler( e ) {
  314. eventHandlerType = e.type;
  315. }
  316. return eventHandlerType === event;
  317. },
  318. scrollTune : function ( opt ){
  319. // $("body").scrollTune({ pps: 1700, pageY: config.pageY, easing:'easeOutSmoothBounce', hsc: true }).promise()
  320. // .done( function() { setTimeout(function(){ toggleClassState( config, 'fullPlayer', type ); },100); })
  321.  
  322. console.log('scrollTune');
  323.  
  324. var position,
  325. defaults = {
  326. tune: 0,
  327. speed: 0,
  328. pps: false, // pixel per second
  329. ppsM: 1000,
  330. pageYmini: 0,
  331. pageY: false, //{ pps: 300, pageY: event.pageY }
  332. hsc: false, // height speed compensation
  333. animate: false,
  334. // require http://gsgd.co.uk/sandbox/jquery/easing/jquery.easing.1.3.js or jQueryUI - if other than ' swing or linear '
  335. easing: "easeInOutCubic", // easeInOutCubic easeInOutQuad easeInOutElastic http://easings.net/
  336. delay: 0,
  337. varStore: '',
  338. varAltStore:false,
  339. name: false,
  340. start: false,
  341. startTime: 0,
  342. step: false,
  343. stepTime: 0,
  344. complete: false,
  345. completeTime: 0,
  346. done: false,
  347. doneTime: 0,
  348. goTo: $('body')
  349. },
  350. heightSpeedComp = function(){ return opt.hsc ? 1 + ( ( $(document).height() / opt.pageY ) / 1.4 ) : 1 ; },
  351. varStore = function( action, step ){
  352. opt.name !== false
  353. ? opt.varAltStore !== false
  354. ? (console.log('Store'), opt.varAltStore[opt.name][ action ](step))
  355. : (console.log('Store false'), opt.name[ action ](step))
  356. : opt.pageYmini < opt.pageY || opt.varStore === config
  357. ? (console.log('config'), opt.varStore[ action ](step))
  358. : (console.log('config false'), opt.varStore(step));
  359.  
  360. /* opt.varAltStore !== false
  361. ? opt.varAltStore[opt.name][ action ]()
  362. : opt.varStore === config
  363. ? opt.name === false
  364. ? opt.varStore[ action ]()
  365. : opt.varStore[ opt.name ][ action ]()
  366. : opt.varStore();*/
  367. };
  368.  
  369. console.log('opt.pageY',opt.pageY);
  370. opt = $.extend( {}, defaults, opt );
  371. position = ( $( this ).offset().top + opt.tune ) + 'px';
  372.  
  373. opt.pps !== false || opt.animate !== false || ( typeof opt.speed === 'string' ? opt.speed.length !== 0 : opt.speed !== 0 )
  374. ? (
  375. opt.speed = opt.pps !== false ? parseInt( ( opt.pageY / opt.pps * heightSpeedComp() ) * opt.ppsM ) : opt.speed,
  376. opt.goTo.delay( opt.delay ).animate(
  377. { scrollTop : position },
  378. { duration : opt.speed, easing: opt.easing,
  379. start : function(){
  380. opt.start && setTimeout(function(){
  381. console.log('start');
  382. varStore('start');
  383. }, opt.startTime );
  384. },
  385. step : function(i){
  386. opt.step && setTimeout(function(){
  387. console.log('step',i);
  388. varStore('step',i);
  389. }, opt.stepTime );
  390. },
  391. complete : function(){
  392. opt.complete && setTimeout(function(){
  393. console.log('complete');
  394. varStore('complete');
  395. }, opt.completeTime );
  396. },
  397. done : function(){
  398. opt.done && setTimeout(function(){
  399. console.log('done');
  400. varStore('done');
  401. }, opt.doneTime );
  402. }
  403. }
  404. )
  405. )
  406. : opt.goTo.scrollTop( position );
  407.  
  408. return this; // for chaining...
  409.  
  410. },
  411. scrollTuneOld : function ( opt ){
  412.  
  413. var position,
  414. defaults = {
  415. tune: 0,
  416. speed: 512,
  417. animate: false,
  418. goTo: $('html, body')
  419. };
  420.  
  421. opt = $.extend( {}, defaults, opt );
  422. position = ( $( this ).offset().top + opt.tune ) + 'px';
  423.  
  424. opt.animate !== false || ( typeof opt.speed === 'string' ? opt.speed.length !== 0 : opt.speed !== 0 )
  425. ? opt.goTo.animate({ scrollTop: position }, opt.speed )
  426. : opt.goTo.scrollTop( position );
  427.  
  428. return this; // for chaining...
  429. }
  430. });
  431.  
  432. $.extend({
  433. confirm: function (title, message, yesText, noText, yesCallback) {
  434. //dialog needs jQueryUI
  435. /*
  436. $.confirm(
  437. "CONFIRM", //title
  438. "Delete " + filename + "?", //message
  439. "Delete", //button text
  440. deleteOk //"yes" callback
  441. );
  442. */
  443. $("<div></div>").dialog( {
  444. buttons: [{
  445. text: yesText,
  446. click: function() {
  447. yesCallback();
  448. $( this ).remove();
  449. }
  450. },
  451. {
  452. text: noText,
  453. click: function() {
  454. $( this ).remove();
  455. }
  456. }
  457. ],
  458. close: function (event, ui) { $(this).remove(); },
  459. resizable: false,
  460. title: title,
  461. modal: true
  462. }).text(message).parent().addClass("alert");
  463. }
  464. });
  465. $.extend( $.expr[":"], {
  466. ldata: function(el, idx, selector) {
  467. var attr = selector[3].split(", ");
  468. return el.dataset[attr[0]] === attr[1];
  469. },
  470. value: function(el, idx, selector) {
  471. return el.value === selector[selector.length - 1];
  472. },
  473. isEmptyTrimmed: function(el){
  474. return !$.trim($(el).html());
  475. },
  476. data: $.expr.createPseudo
  477. ? $.expr.createPseudo(function( dataName ) {
  478. return function( elem ) {
  479. return !!$.data( elem, dataName );
  480. };
  481. })
  482. // support: jQuery <1.8
  483. : function( elem, i, match ) {
  484. return !!$.data( elem, match[ 3 ] );
  485. }
  486. });
  487.  
  488. Object.defineProperty(HTMLMediaElement.prototype, 'playing', {
  489. //$( selector ).get(0).playing;
  490. get: function(){
  491. return !!( this.currentTime > 0 && !this.paused && !this.ended && this.readyState > 2 );
  492. }
  493. });
  494. /* Object.prototype.hasAttribute = function( attrName, val ){
  495. var thisAttr =
  496. this.attr
  497. ? val !== undefined
  498. ? this.attr( attrName ) === val
  499. : this.attr( attrName )
  500. : this.getAttribute( attrName );
  501. return ( typeof thisAttr !== "undefined" && thisAttr !== false && thisAttr !== null );
  502. };
  503. */
  504. Array.prototype.findArrayObj = function( findKey, exactValue ){
  505. return $.grep( this, function( obj ){
  506. return obj[ findKey ] === exactValue;
  507. })[0];
  508. //This prototype doesn't modify the array,
  509. // it gets the element that contains key with correct value and
  510. // the returns that element
  511. };
  512. Array.prototype.removeArrayObj = function( findKey, exactValue ){
  513. //my own example test: http://jsfiddle.net/aPH7m/82/
  514. //This prototype doesn't modify the array, needs to be overwritten or put into new var array
  515. return $.grep( this, function( obj ) {
  516. return obj[ findKey ] !== exactValue;
  517. });
  518. };
  519. Array.prototype.addKeyToArrayObj = function( findKey, exactValue, newKey, newValue ){
  520. return $.grep( this, function( obj ){
  521. return obj[ findKey ] === exactValue ? obj[ newKey ] = newValue : obj[ findKey ] !== exactValue;
  522. });
  523. // This prototype doesn't modify the array,
  524. // it gets the element that contains key with correct value and
  525. // adds a new key with its value to that element
  526. };
  527.  
  528. Array.prototype.filterArrayObj = function( doWhat, findKey, exactValue, newKey, newValue ){
  529. return doWhat === 'remove'
  530. ? this.filter(function( obj ) {
  531. return obj[ findKey ] !== exactValue;
  532. })
  533. : doWhat === 'addKey'
  534. ? this.filter(function( obj ){
  535. return obj[ findKey ] === exactValue
  536. ? obj[ newKey ] = newValue
  537. : obj[ findKey ] !== exactValue;
  538. })
  539. : doWhat === 'find'
  540. && this.filter(function( obj ){
  541. return obj[ findKey ] === exactValue;
  542. })[0];
  543. };
  544. Array.prototype.grepArrayObj = function( doWhat, idKey, uniqueValue, theKey, theValue ){
  545. doWhat = doWhat === 'updateKey' ? 'addKey' : doWhat;
  546. return doWhat === 'remove'
  547. ? $.grep( this, function( obj ){
  548. return obj[ idKey ] !== uniqueValue;
  549. })
  550. : doWhat === 'addKey'
  551. ? $.grep( this, function( obj ){
  552. return obj[ idKey ] === uniqueValue
  553. ? (
  554. obj[ theKey ] = theValue,
  555. obj[ idKey ] === uniqueValue
  556. )
  557. : obj[ idKey ] !== uniqueValue;
  558. })
  559. : doWhat === 'find'
  560. ? $.grep( this, function( obj ){
  561. return obj[ idKey ] === uniqueValue;
  562. })[0]
  563. : doWhat === 'deleteKey'
  564. && $.grep( this, function( obj ){
  565. return obj[ idKey ] === uniqueValue
  566. ? (
  567. delete obj[ theKey ],
  568. obj[ idKey ] === uniqueValue
  569. )
  570. : obj[ idKey ] !== uniqueValue;
  571. })
  572. };
  573.  
  574. String.prototype.splitEvery = function( splitter, every ){
  575. var array = this.split( splitter ), newString = '';
  576. $.each( array, function( index, elem ){
  577. newString += elem + ( index < array.length - 1 || index % every === 0 ) ? '' : splitter;
  578. });
  579. return newString;
  580. };
  581. String.prototype.advSplit = function( chr, nbr ){
  582. var str = this.split(chr),
  583. strLen = str.length,
  584. chrLen = chr.length,
  585. newStr = ['',''],
  586. newArr = [];
  587.  
  588. $.each( str, function( index ){
  589. newStr[ index < nbr ? 0 : 1 ] += str[ index ] + chr;
  590. });
  591.  
  592. $.each( newStr, function( index ){
  593. newStr[ index ] = newStr[ index ].slice(0, - chrLen);
  594. newStr[ index ].length > 0 && newArr.push( newStr[ index] );
  595. });
  596.  
  597. return newArr;
  598. };
  599. String.prototype.advSplitJoin = function( chr, nbr, ips ){
  600.  
  601. var str = this.split(chr),
  602. strLen = str.length,
  603. ipsLen = ips.length,
  604. newStr = '',
  605. newStrLen;
  606.  
  607. $.each( str, function( index ) {
  608. var add = index < strLen - 1
  609. ? chr
  610. : '';
  611. newStr += index + 1 === nbr
  612. ? str[index] + ips
  613. : str[index] + add;
  614. });
  615.  
  616. newStrLen = newStr.length;
  617. newStr.slice( newStrLen - ipsLen ) === ips
  618. && ( newStr = newStr.slice( 0, newStrLen - ipsLen ) );
  619.  
  620. return newStr;
  621. };
  622. String.prototype.extract = function( start, end, inside, newWay ){
  623. var str = this,
  624. myArray = [ true, 1, 'yes', 'inside' ],
  625. startCharIndex = str.indexOf( start ),
  626. endCharIndex = str.indexOf( end );
  627.  
  628. newWay = newWay !== undefined ? $.inArray( newWay, myArray ) !== -1 : false;
  629. inside = inside !== undefined ? $.inArray( inside, myArray ) !== -1 : false;
  630.  
  631. function simpler() {
  632. return inside
  633. ? str.split( start ).pop().split( end ).shift()
  634. : start + str.split( start ).pop().split( end ).shift() + end;
  635. }
  636. function older() {
  637. return inside //old buggy way, some old scripts may depends on it
  638. ? str.replace( start, '').replace( end, '')
  639. : str.substr( startCharIndex, endCharIndex );
  640. }
  641. return newWay ? simpler() : older()
  642. };
  643. String.prototype.extractNew = function( start, end, inside ){
  644. var str = this;
  645. return inside !== undefined && inside
  646. ? str.split( start ).pop().split( end ).shift()
  647. : inside
  648. || start + str.split( start ).pop().split( end ).shift() + end;
  649. };
  650.  
  651. String.prototype.charTrim = function( char ){
  652. // alert("...their.here.".charTrim('.'));
  653. var first_pos = 0,
  654. last_pos = this.length- 1, i ;
  655. //find first non needle char position
  656. for( i = 0; i < this.length; i++ ){
  657. if( this.charAt( i ) !== char ){
  658. first_pos = ( i == 0 ? 0 : i );
  659. break;
  660. }
  661. }
  662. //find last non needle char position
  663. for( i = this.length - 1; i > 0; i-- ){
  664. if( this.charAt( i ) !== char ){
  665. last_pos = ( i == this.length ? this.length: i + 1 );
  666. break;
  667. }
  668. }
  669. return this.substring( first_pos, last_pos );
  670. };
  671. String.prototype.reduceWhiteSpace = function(){
  672. return this.replace(/\s+/g, ' ');
  673. };
  674. String.prototype.formatString = function(){
  675. return this.toString()
  676. .split('!').join(' !').split('!;').join("!important;")
  677. .split(/\s+/g).join(' ')
  678. .split('{').join('{\n\t')
  679. .split('; ').join(';')
  680.  
  681. .split('( ').join('(')
  682. .split(' )').join(')')
  683.  
  684. .split(' :').join(':')
  685. .split(';').join(';\n\t')
  686. .split('*/').join('*/\n')
  687. .split(')*(').join(') * (')
  688. .split('}').join('}\n');
  689. };
  690.  
  691.  
  692. String.prototype.undef = function( replace ){
  693. return this === undefined ? replace : this;
  694. };
  695. String.prototype.isUndefined = function( state, replace ){
  696. state = state !== undefined ? state : true;
  697. replace = replace !== undefined ? replace : true;
  698. return state ? this === undefined ? replace : this : state;
  699. };
  700. String.prototype.parseBool = function(){
  701. var str = parseInt( this ) ? this === 0 ? 'false' : 'true' : '' + this,
  702. trueArray = [ 'on', 'yes','y', 'j', 'true' ],
  703. falseArray = [ 'off', 'no', 'n', 'false' ];
  704.  
  705. str = str.toLowerCase().trim();
  706.  
  707. return $.inArray( str, trueArray ) !== -1 ? true :
  708. $.inArray( str, falseArray ) !== -1 ? false : this;
  709. };
  710.  
  711. String.prototype.inURL = function(){
  712. var winLoc = window.location.href;
  713. return winLoc.search(this) !== -1;
  714. };
  715. String.prototype.inString = function( string ){
  716. return string !== undefined ? string.search(this) !== -1 : false;
  717. };
  718. String.prototype.inElem = function( search ){
  719. return this !== undefined ? this.search(search) !== -1 : false;
  720. };
  721. String.prototype.count = function( char, UpperCase ){
  722. var numberOf = this.toString().match( new RegExp( char, ( UpperCase ? "gi" : "g" ) ) );
  723. return numberOf != null ? numberOf.length : 0;
  724. };
  725. String.prototype.startsWith = function( str ){
  726. return this.slice(0, str.length) == str;
  727. };
  728. String.prototype.removeStarts = function( many ){
  729. return this.substring( many - 1, this.length );
  730. };
  731. String.prototype.removeEnds = function( many ){
  732. return this.substring( 0, this.length - many );
  733. };
  734. String.prototype.endsWith = function( str ){
  735. return this.slice( -str.length ) == str;
  736. };
  737. String.prototype.capitalizeFirst = function(){
  738. return this.charAt(0).toUpperCase() + this.slice(1);
  739. };
  740. String.prototype.lpad = function( padString, length ){
  741. var str = this;
  742. while ( str.length < length ) {
  743. str = padString + str; }
  744. return str;
  745. };
  746.  
  747. // use full to convert String URL, so that you can use location commands
  748. String.prototype.toLocation = function(){
  749. var a = document.createElement('a');
  750. a.href = this;
  751. return a;
  752. };
  753. String.prototype.str2html = function(){
  754. return $('<div/>').html( this ).contents();
  755. };
  756. String.prototype.toStyle = function( styleId ){
  757. var cssID,
  758. cssSplit = this.split('¤'),
  759. cssStyled = cssSplit.pop().formatString();
  760. styleId = styleId !== undefined ? styleId : cssSplit.shift();
  761. cssID = $( 'head #' + styleId );
  762. cssID.length
  763. ? cssID.html( cssStyled )
  764. : $( $( '<style/>',{ id: styleId, class:'mySuperStyles', html: cssStyled } ) ).appendTo('head');
  765. };
  766.  
  767. //HTMLObjectElement.prototype.obj2Str = function(){var objArr = $.makeArray( this ); return objArr[0].outerHTML;};
  768. /*
  769. String.prototype.replaceAll = function( target, replacement ) {
  770. return this.split(target).join(replacement);
  771. };
  772. */
  773. function ScrollZoomTune( selection, zooms, tune, ani, speed ){
  774. //ScrollZoomTune("div.thumb .title a",1,-25,1,'slow');
  775. var body = $('body'), sel = $( selection), position;
  776. //noinspection JSValidateTypes
  777. sel.size() !== 0 && (
  778. body.css('zoom',zooms),
  779. position = sel.position().top + tune,
  780. ani === 1
  781. ? body.animate({ scrollTop: position * zooms }, speed )
  782. : body.scrollTop( position * zooms )
  783. );
  784. }
  785. function refreshElement( elem , speed ){ //refreshElement('.videoPlayer','slow');
  786. var $elem = $( elem ), data = $elem.html();
  787. $elem.empty().html( data ).fadeIn( speed );
  788. }
  789. function autoCopyToClipboard( input ){
  790. var $copyThis = $( '#copyThis' );
  791. $( 'body' ).append( $('<textarea/>',{ id:'copyThis', rows:"4", cols:"50", type:"text", value: input }) );
  792. $copyThis.focus().select();
  793. document.execCommand("copy");
  794. $copyThis.remove();
  795. }
  796. function toStyle( styleId, str ){
  797. var $id = $( 'head #' + styleId ),
  798. cssID = str.formatString();
  799. $id.length
  800. ? $id.html( cssID )
  801. : $( $( '<style/>',{ id: styleId, class:'mySuperStyles', html: cssID } ) ).appendTo('head');
  802. }
  803. function obj2Str( obj ){
  804. var objArr = $.makeArray(obj);
  805. return objArr[0].outerHTML;
  806. }
  807.  
  808. function sortBy(key, reverse) {
  809. // Usage: array.sort( sorBy( key, reverse ) )
  810.  
  811. // Move smaller items towards the front
  812. // or back of the array depending on if
  813. // we want to sort the array in reverse
  814. // order or not.
  815. var moveSmaller = reverse ? 1 : -1;
  816. // Move larger items towards the front
  817. // or back of the array depending on if
  818. // we want to sort the array in reverse
  819. // order or not.
  820. var moveLarger = reverse ? -1 : 1;
  821. /**
  822. * @param {*} a
  823. * @param {*} b
  824. * @return {Number}
  825. */
  826. return function (a, b) {
  827. if (a[key] < b[key]) {
  828. return moveSmaller;
  829. }
  830. if (a[key] > b[key]) {
  831. return moveLarger;
  832. }
  833. return 0;
  834. };
  835.  
  836. }
  837.  
  838. function VideoTitleA( elem , state ){
  839. $( elem ).each(function(){
  840. var $this = $(this),
  841. strTitle = $this.attr('title'),
  842. strText = $this.attr('data-text'),
  843. strHtml = $this.text();
  844. state === 'on' ? $this.text(strTitle).attr('data-text',strHtml) : $this.text(strText);
  845. });
  846. }
  847. /**
  848. * @return {string}
  849. */
  850. function MultiString( f ){
  851. return f.toString().split('\n').slice(1, -1).join('\n');
  852. }
  853. function wrapWithTag( tag, text, selection ){
  854. var thisAttr = selection != undefined && selection.startsWith('.') ? 'class' : selection.startsWith('#') && 'id',
  855. thisTag = $('<' + tag + '/>', { text: text });
  856. return thisAttr.length ? thisTag.attr( thisAttr, selection.splice( 1 ) ) : thisTag;
  857. }
  858.  
  859. function clean( node ) {
  860. /*
  861. So to clean those unwanted nodes from inside the <body> element, you would simply do this:
  862.  
  863. clean(document.body);
  864. Alternatively, to clean the entire document, you could do this:
  865.  
  866. clean(document);
  867. */
  868. for( var n = 0; n < node.childNodes.length; n ++ ){
  869. var child = node.childNodes[ n ];
  870. ( child.nodeType === 8 || ( child.nodeType === 3 && !/\S/.test( child.nodeValue ) ) )
  871. ? (
  872. node.removeChild( child ),
  873. n --
  874. )
  875. : child.nodeType === 1 && clean( child );
  876. }
  877. }
  878. function commentsCleaner(){
  879. // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
  880. // http://stackoverflow.com/a/2364760
  881. $.each( [ '*', document, 'html' ], function( i, e ) {
  882. $( e ).contents().each( function() {
  883. this.nodeType === Node.COMMENT_NODE && $( this ).remove(); }); });
  884. }
  885.  
  886. function inURL( search ){
  887. var winLoc = window.location.href;
  888. return winLoc.search( search ) !== -1;
  889. }
  890. function loadDoc( href ){
  891. $( location ).attr('href', href );
  892. }
  893.  
  894. function isPrimitiveType( value ){
  895. // will return true if the value is a primitive value
  896. switch ( typeof value ) {
  897. case 'string': case 'number': case 'boolean': case 'undefined': {
  898. return true;
  899. }
  900. case 'object': {
  901. return !value;
  902. }
  903. }
  904. return false;
  905. }
  906. function checkDividedIsInteger( num, div ){
  907. return ( num % div === 0 );
  908. }
  909. function isEven( value ){
  910. return ( value % 2 === 0 );
  911. }
  912. function inDom( array, onElement ) {
  913. var found = false;
  914. $.each( array, function( i, value ) {
  915. value = onElement !== undefined
  916. ? onElement + value
  917. : value;
  918. if( $( value ).length ) {
  919. found = true;
  920. return false;
  921. }
  922. });
  923. /**
  924. * @return {boolean}
  925. */
  926. return found;
  927. }
  928. function isHTMLObject( obj ){
  929. obj = typeof obj == 'string' ? obj : $( obj );
  930. return obj.length
  931. ? !!( obj instanceof HTMLElement || obj[0] instanceof HTMLElement)
  932. : !!( obj && ( obj.nodeName || ( obj.prop && obj.attr && obj.find ) ) );
  933. }
  934.  
  935. function isFunction( functionToCheck ){
  936. var getType = {};
  937. return functionToCheck && getType.toString.call( functionToCheck ) === '[object Function]';
  938. }
  939. function isNumeric( value ){
  940. return /^\d+$/.test( value );
  941. }
  942.  
  943. function toggleClassState( config, Class, state, elem ){
  944. config[ Class ] = typeof state === 'string' ? !config[ Class ] : state;
  945. $( elem || 'html' )[ config[ Class ] ? 'addClass' : 'removeClass' ]( Class );
  946. }
  947. function filterClick( e, $this ){
  948. return e.which == 1 && e.target == $this;
  949. }
  950. function dispatchEventResize() {
  951. //noinspection JSClosureCompilerSyntax,JSUnresolvedFunction
  952. window.dispatchEvent(new Event('resize'));
  953. }
  954.  
  955. /**
  956. * @return {string}
  957. */
  958. function Undefined( check, replace ){
  959. return check === undefined ? replace.toString() : check.toString();
  960. }
  961.  
  962. function getGlobal(){
  963. return (function(){
  964. return this;
  965. })();
  966. }
  967. function GM_lister( remove, item ){
  968. var keys = GM_listValues();
  969. for (var i = 0, key = null; key = keys[i]; i++) {
  970. GM_listValues()[i] !== undefined && (
  971. c.i('GM_ListItem: ' + GM_listValues()[i], GM_getValue(key)),
  972. ( ( item !== undefined && GM_listValues()[i].inElem( item ) ) || item === undefined )
  973. && ( remove === true || remove === 'yes' || remove === 1 ) && GM_deleteValue(key));
  974. }
  975. }
  976.  
  977. function roundFloat( num, dec ){
  978. var d = 1;
  979. for ( var i=0; i<dec; i++ ){
  980. d += "0";
  981. }
  982. return Math.round(num * d) / d;
  983. }
  984. function randomFloatBetween( min, max, dec ){
  985. dec = typeof( dec ) == 'undefined' ? 2 : dec;
  986. return parseFloat( Math.min( min + ( Math.random() * ( max - min ) ), max ).toFixed( dec ) );
  987. }
  988. function random( max ) {
  989. var min = 1,
  990. rand = function(){
  991. return Math.floor( Math.random() * ( max - min + 1 ) + min );
  992. },
  993. num1 = rand(),
  994. num2 = rand();
  995.  
  996. return ( num1 > num2 ? num2/num1 : num1/num2 ) * max;
  997. }
  998. function roundNearPeace( number, peaces, dec ) {
  999. return ( Math.round( number * peaces ) / peaces ).toFixed( dec );
  1000. }
  1001.  
  1002. //VideoTitleA("div.thumb .title a",'on');
  1003. var w = window,
  1004. glob = w,
  1005. $w = $( w ),
  1006. $l = $( location ),
  1007. locDoc = window.location.href,
  1008. d = document,
  1009. $d = $( d ),
  1010.  
  1011. c = {
  1012. defaultState: 3,
  1013. cute : function( type, msg, color ) {
  1014. color = color || "black";
  1015. var newColor, bgc = "White";
  1016. switch ( color ) {
  1017. case "success": newColor = "Green"; bgc = "LimeGreen"; break;
  1018. case "info": newColor = "DodgerBlue"; bgc = "Turquoise"; break;
  1019. case "error": newColor = "Red"; bgc = "Black"; break;
  1020. case "start": newColor = "OliveDrab"; bgc = "PaleGreen"; break;
  1021. case "warning": newColor = "Tomato"; bgc = "Black"; break;
  1022. case "end": newColor = "Orchid"; bgc = "MediumVioletRed"; break;
  1023. default: //noinspection SillyAssignmentJS
  1024. newColor = color;
  1025. }
  1026.  
  1027. typeof msg == "object" ?
  1028. window.console[ type ]( msg )
  1029. : typeof color == "object" ? (
  1030. window.console[ type ]("%c" + msg, "color: PowderBlue;font-weight:bold; background-color: RoyalBlue;"),
  1031. window.console[ type ]( newColor )
  1032. ) :
  1033. window.console[ type ]("%c" + msg, "color:" + newColor + "; background-color: " + bgc + ";")
  1034. },
  1035. show: function( showThis, type ){
  1036. var State = GM_getValue( type + 'StateValue' ) || this.defaultState;
  1037. return showThis !== 0 && State !== 0 && State === ( showThis || State ) || State === 'all';
  1038. },
  1039. pre: function( type, name, fn, line, color ){
  1040. line = line == undefined ? '' : line + ': ';
  1041. var Fn = function(){ return fn !== undefined ? fn : ''; };
  1042. typeof fn == "object" ?
  1043. window.console[ type ]( name, Fn() ) : c.cute( type, line + name + ': ' + Fn(), color );
  1044. },
  1045. l: function( name, fn, line, color, showThis ){
  1046. var type = 'log';
  1047. this.show( showThis, type ) && this.pre( type, name, fn, line, color );
  1048. },
  1049. h: function( name, fn, line, color, showThis ){
  1050. var type = 'handled';
  1051. this.show( showThis, type ) && this.pre( type, name, fn, line, color );
  1052. },
  1053. //c.l('name', 'fn'=='fn', 'line', 'blue')
  1054. i: function( name, fn, line, color, showThis ){
  1055. var type = 'info';
  1056. this.show( showThis, type ) && this.pre( type, name, fn, line, color );
  1057. },
  1058. d: function( name, fn, line, color, showThis ){
  1059. var type = 'debug';
  1060. this.show( showThis, type ) && this.pre( type, name, fn, line, color );
  1061. }
  1062. },
  1063. localStorageObj = {
  1064. name : 'setName', //important
  1065. localArray : function(){
  1066. return localStorage.getItem( this.name )
  1067. },
  1068. getArray : function(){
  1069. return this.localArray() === null ? [] : JSON.parse( this.localArray() )
  1070. },
  1071. stringify : function( array ){
  1072. localStorage.setItem( this.name, array );
  1073. },
  1074. check : function( array, key, value ){
  1075. return array.grepArrayObj('find', key, value );
  1076. },
  1077. viewConsole : function( json ){
  1078. var array = this.getArray();
  1079. // $.toJSON() --- https://github.com/Krinkle/jquery-json/blob/master/src/jquery.json.js
  1080. // array.join('\n');
  1081. c.d( this.name, array ); //debug mode important to make this work
  1082. c.i( this.name, json ? isFunction( $.toJSON() ) ? $.toJSON( array ) : JSON.stringify( array ) : array.toSource() );
  1083. },
  1084. add : function( key, value, obj ){
  1085. var array = this.getArray();
  1086. this.check( array, key, value )
  1087. || (
  1088. array.push( obj ),
  1089. c.i('[Added Object into array]', obj )
  1090. );
  1091. this.stringify( array )
  1092. },
  1093. remove : function( key, value, obj ){
  1094. var array = this.getArray();
  1095. this.check( array, key, value )
  1096. || (
  1097. array = array.grepArrayObj('remove', key, value ),
  1098. c.i('[Removed Object from array]', obj )
  1099. );
  1100. this.stringify( array );
  1101. }
  1102. },
  1103. booleanTimer = {
  1104. timers : [],
  1105. start : function( name, ms ){
  1106. var that = this, value = name,
  1107. stop = setTimeout(function(){
  1108. that.stop( value );
  1109. }, ms );
  1110. this.timers.push( { 'name': value, stop:stop } );
  1111. setTimeout(function(){
  1112. that.stop( value );
  1113. }, ms );
  1114. },
  1115. check : function( value ){
  1116. return this.timers.grepArrayObj( 'find', 'name', value ) !== undefined;
  1117. },
  1118. stop : function( value ){
  1119. this.timers = this.timers.grepArrayObj( 'remove', 'name', value );
  1120. }
  1121. },
  1122. advTimer = {
  1123. timers : [],
  1124. start : function( name, ms ){
  1125. var that = this, value = name,
  1126. stop = setTimeout(function(){
  1127. that.stop( value );
  1128. }, ms );
  1129. //noinspection JSUnresolvedVariable
  1130. this.timers.push( { 'name': value, start: window.performance.now(), timeout: ms, stop:stop } );
  1131. },
  1132. check : function( value ){
  1133. var findObj = this.timers.grepArrayObj( 'find', 'name', value );
  1134. //noinspection JSUnresolvedVariable
  1135. return findObj !== undefined
  1136. ? findObj.timeout - ( window.performance.now() - findObj.start )
  1137. : false;
  1138. },
  1139. stop : function( value ){
  1140. this.timers = this.timers.grepArrayObj( 'remove', 'name', value );
  1141. }
  1142. },
  1143. lap = {
  1144. data : {},
  1145. tid : function(){
  1146. //noinspection JSUnresolvedVariable
  1147. return performance.now();
  1148. },
  1149. set : function(name){
  1150. this.data[name] = this.tid();
  1151. },
  1152. get : function(name){
  1153. return this.tid() - this.data[name];
  1154. },
  1155. end : function(name){
  1156. this.print(name);
  1157. this.del(name);
  1158. },
  1159. del : function(name){
  1160. delete this.data[name];
  1161. },
  1162. print: function(name){
  1163. var get = this.get( name );
  1164. c.i( 'Lap: ' + name, isNaN( get ) ? 'There is no such a name ' : get + 'ms' );
  1165. }
  1166. },
  1167. timer = {
  1168. ms : 0,
  1169. set : function(ms){
  1170. var that = this;
  1171. this.ms = ms;
  1172. setTimeout(function(){
  1173. that.ms = 0;
  1174. }, ms );
  1175. }
  1176. },
  1177. g = {
  1178. locDoc : window.location.href,
  1179. ms : 0,
  1180. timer : function(ms){
  1181. g.ms = ms;
  1182. setTimeout(function(){ g.ms = 0; }, ms );
  1183. },
  1184.  
  1185. GM : {
  1186. engine : function( mode, val, range ){
  1187. switch (mode){
  1188. case 'set': GM_setValue( val.name, val.default );
  1189. break;
  1190. case 'get': range ? config[ val.name ] = GM_getValue( val.name ):
  1191. ui.config[ val.name ] = GM_getValue( val.name );
  1192. break;
  1193. case 'del': GM_deleteValue( val.name );
  1194. }
  1195. },
  1196. manager : function( mode, array, range ){
  1197. $.each( array, function( i, val ){ this.engine( mode, val, range === undefined ); });
  1198. mode === 'del' && ( GM_deleteValue( 'firstRun' ), GM_deleteValue( 'yourVer' ) );
  1199. }
  1200. }
  1201. },
  1202.  
  1203. testPerformance = function( name, fn, testCycles ) {
  1204. lap.set( name );
  1205. var i = 0;
  1206. for ( i ; i < testCycles; i++ ){
  1207. fn;
  1208. }
  1209. lap.end( name );
  1210. },
  1211. perf = function (testName, fn) {
  1212. var startTime = new Date().getTime();
  1213. fn();
  1214. var endTime = new Date().getTime();
  1215. console.log(testName + ": " + (endTime - startTime) + "ms");
  1216. };
  1217.  
  1218. $(document).on('click','*',function(e){
  1219. this == e.target && c.i('target:', e.target ); });
  1220.  
  1221. c.i('my Function Library ö');
  1222. /*
  1223. isScrolledIntoView = (elem) ->
  1224. docViewTop = $(window).scrollTop()
  1225. docViewBottom = docViewTop + $(window).height()
  1226. elemTop = $(elem).offset().top
  1227. elemBottom = elemTop + $(elem).height()
  1228.  
  1229. (elemBottom - 200 < docViewBottom) and (elemBottom + $(elem).height() > docViewBottom )
  1230. */