util.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. window.Tracker = window.Tracker || {};
  2. Tracker.Util = function(){
  3. var fileNameSplitWord = /[?#]/;
  4. var excapeRegx = function(){
  5. var specials, regx;
  6. specials = [ "/", ".", "*", "+", "?", "|", "$", "^", "(", ")", "[", "]", "{",
  7. "}", "\\" ];
  8. regx = new RegExp( "(\\" + specials.join("|\\") + ")", "g" );
  9. return function( text ){
  10. return text.replace( regx, "\\$1" );
  11. };
  12. }();
  13. var RemoteProxy = function(){
  14. var callbacks, esc, service, timeout;
  15. callbacks = {};
  16. timeout = 10e3;
  17. document.remoteProxyCallback = function( data ){
  18. var c;
  19. if( c = callbacks[ data.url ] )
  20. c( data );
  21. };
  22. esc = function(){
  23. var regx, rep;
  24. regx = /[\\\/ \+%&=#\?]/g;
  25. rep = function( s ){
  26. return escape( s );
  27. };
  28. return function( url ){
  29. return url.replace( regx, rep );
  30. };
  31. }();
  32. service = "http://www.ucren.com/tracker/proxy.php";
  33. var getProxyUrl = function( url ){
  34. url = Tracker.Util.param( service, "url", esc( url ) );
  35. url = Tracker.Util.param( url, "callback", "remoteProxyCallback" );
  36. return url;
  37. };
  38. return {
  39. get: function( url, charset ){
  40. var pm, timer, script;
  41. pm = new Tracker.Promise();
  42. script = Tracker.Util.makeElement( document, "script" );
  43. script.src = getProxyUrl( url );
  44. script.charset = charset || "utf-8";
  45. document.head.appendChild( script );
  46. callbacks[ url ] = function( data ){
  47. clearTimeout( timer );
  48. pm.resolve( {
  49. response: data.content,
  50. consum: data.consum
  51. } );
  52. script = null;
  53. delete callbacks[ url ];
  54. };
  55. timer = setTimeout( function(){
  56. script.parentNode.removeChild( script );
  57. pm.reject();
  58. script = null;
  59. }, timeout );
  60. return pm;
  61. },
  62. request : function(url) {
  63. var pm = new Tracker.Promise();
  64. var timeStart = Tracker.Util.time();
  65. var timer = setTimeout( function(){
  66. pm.reject();
  67. }, timeout );
  68. //向background发送一个消息,要求其加载并处理js文件内容
  69. chrome.extension.sendMessage({
  70. type : MSG_TYPE.GET_JS,
  71. link : url
  72. },function(respData){
  73. clearTimeout( timer );
  74. pm.resolve( {
  75. response: respData.content,
  76. consum: Tracker.Util.time() - timeStart
  77. } );
  78. });
  79. return pm;
  80. }
  81. };
  82. }();
  83. return {
  84. blank: function(){
  85. },
  86. bind: function( fn, scope ){
  87. return function(){
  88. return fn.apply( scope, arguments );
  89. };
  90. },
  91. forEach: function( unknow, iterator ){
  92. var i, l;
  93. if( unknow instanceof Array ||
  94. ( unknow && typeof unknow.length == "number" ) )
  95. for( i = 0, l = unknow.length; i < l; i ++ )
  96. iterator( unknow[ i ], i, unknow );
  97. else if( typeof unknow === "string" )
  98. for( i = 0, l = unknow.length; i < l; i ++ )
  99. iterator( unknow.charAt( i ), i, unknow );
  100. },
  101. // map: function( array, fn ){
  102. // for( var i = 0, l = array.length; i < l; i ++ )
  103. // array[ i ] = fn( array[ i ], i, array );
  104. // },
  105. id: function(){
  106. return "_" + this.nid();
  107. },
  108. nid: function( id ){
  109. return function(){
  110. return id ++;
  111. }
  112. }( 1 ),
  113. handle: function(){
  114. var cache, number;
  115. cache = [];
  116. number = -1;
  117. return function( unknown ){
  118. var type;
  119. type = typeof unknown;
  120. if( type == "number" )
  121. return cache[ unknown ];
  122. else if( type == "object" || type == "function" ){
  123. cache[ ++ number ] = unknown;
  124. return number;
  125. }
  126. }
  127. }(),
  128. trim: function(){
  129. var regx = /^\s+|\s+$/g, rep = "";
  130. return function( string ){
  131. return string.replace( regx, rep );
  132. }
  133. }(),
  134. random: function(){
  135. return ( Math.random() * 1e6 ) | 0;
  136. },
  137. getByteLength: function( string ){
  138. return string.replace( /[^\x00-\xff]/g, " " ).length;
  139. },
  140. makeElement: function( doc, tagName, cssText ){
  141. var el;
  142. if( typeof doc == "string" )
  143. cssText = tagName,
  144. tagName = doc,
  145. doc = null;
  146. if( !doc )
  147. doc = document;
  148. el = doc.createElement( tagName );
  149. if( cssText )
  150. el.style.cssText = cssText;
  151. return el;
  152. },
  153. getHtmlComments: function(){
  154. var cn, push;
  155. cn = document.COMMENT_NODE;
  156. push = [].push;
  157. return function f( node ){
  158. var result, c, l, i;
  159. result = [];
  160. if( node.nodeType == cn )
  161. result.push( node.nodeValue );
  162. else if( ( c = node.childNodes ) && ( l = c.length ) )
  163. for( i = 0; i < l; i ++ )
  164. push.apply( result, f( c[ i ] ) );
  165. return result;
  166. }
  167. }(),
  168. findParent: function( el, tag, endOf ){
  169. do{
  170. if( el.tagName.toLowerCase() == tag.toLowerCase() )
  171. return el;
  172. if( el == endOf )
  173. return null;
  174. el = el.parentNode;
  175. }while( 1 );
  176. },
  177. tmpl: function( text, data ){
  178. var settings, render, noMatch, matcher, index, source, escaper, escapes, template;
  179. settings = { evaluate: /<%([\s\S]+?)%>/g, interpolate: /<%=([\s\S]+?)%>/g };
  180. noMatch = /(.)^/;
  181. matcher = new RegExp( [
  182. ( settings.interpolate || noMatch ).source,
  183. ( settings.evaluate || noMatch ).source
  184. ].join('|') + '|$', 'g' );
  185. index = 0;
  186. source = "__p+='";
  187. escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
  188. escapes = {
  189. "'": "'", '\\': '\\', '\r': 'r', '\n': 'n', '\t': 't', '\u2028': 'u2028',
  190. '\u2029': 'u2029'
  191. };
  192. text.replace( matcher, function( match, interpolate, evaluate, offset ){
  193. source += text.slice( index, offset ).replace( escaper, function( match ){
  194. return '\\' + escapes[ match ];
  195. } );
  196. if( interpolate )
  197. source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
  198. if( evaluate )
  199. source += "';\n" + evaluate + "\n__p+='";
  200. index = offset + match.length;
  201. return match;
  202. } );
  203. source += "';\n";
  204. source = 'with(obj||{}){\n' + source + '}\n';
  205. source = "var __t,__p='',__j=Array.prototype.join," +
  206. "print=function(){__p+=__j.call(arguments,'');};\n" + source + "return __p;\n";
  207. try{
  208. render = new Function( 'obj', source );
  209. }catch( e ){
  210. e.source = source;
  211. throw e;
  212. }
  213. if( data )
  214. return render( data );
  215. template = function( data ) {
  216. return render.call( this, data );
  217. };
  218. template.source = 'function(obj){\n' + source + '}';
  219. return template;
  220. },
  221. tag: function( html, tagName, className ){
  222. var result, t;
  223. result = html;
  224. tagName = tagName.split( " " );
  225. while( t = tagName.pop() )
  226. result = "<" + t + ">" + result + "</" + t + ">";
  227. if( className )
  228. result = result.replace( /<(\w+)>/,
  229. "<$1 class='" + className + "'>" );
  230. return result;
  231. },
  232. hasClass: function( el, className ){
  233. var name;
  234. name = " " + el.className + " ";
  235. return ~name.indexOf( " " + className + " " );
  236. },
  237. addClass: function( el, className ){
  238. var name;
  239. name = " " + el.className + " ";
  240. if( !~name.indexOf( " " + className + " " ) )
  241. el.className += " " + className;
  242. },
  243. removeClass: function( el, className ){
  244. var name;
  245. name = " " + el.className + " ";
  246. if( ~name.indexOf( " " + className + " " ) ){
  247. name = name.replace( " " + className + " ", " " );
  248. name = Tracker.Util.trim( name.replace( / +/g, " " ) );
  249. el.className = name;
  250. }
  251. },
  252. html: function( string ){
  253. return string.replace( /&/g, "&amp;" )
  254. .replace( /</g, "&lt;" )
  255. .replace( />/g, "&gt;" )
  256. .replace( /"/g, "&quot;" )
  257. .replace( /'/g, "&#39;" );
  258. },
  259. splitToLines: function(){
  260. var splitLineRegx = /\r\n|[\r\n]/;
  261. return function( string ){
  262. return string.split( splitLineRegx );
  263. }
  264. }(),
  265. param: function( url, name, value ){
  266. var spliter, suffix;
  267. spliter = ~url.indexOf( "?" ) ? "&" : "?";
  268. suffix = name + "=" + value;
  269. return url + spliter + suffix;
  270. },
  271. excapeRegx: excapeRegx,
  272. fileName: function( url ){
  273. url = url.split( fileNameSplitWord )[ 0 ];
  274. return url.slice( url.lastIndexOf( "/" ) + 1 );
  275. },
  276. time: function(){
  277. return new Date().getTime();
  278. },
  279. browser: function(){
  280. var ua, isOpera, ret;
  281. ua = navigator.userAgent;
  282. isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
  283. ret = {
  284. IE: !!window.attachEvent && !isOpera,
  285. Opera: isOpera,
  286. WebKit: ua.indexOf('AppleWebKit/') > -1,
  287. Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1
  288. // MobileSafari: /Apple.*Mobile/.test(ua)
  289. };
  290. for( var name in ret )
  291. if( ret.hasOwnProperty( name ) && ret[ name ] ){
  292. ret.name = name;
  293. break;
  294. }
  295. return ret;
  296. }(),
  297. isCrossDomain: function( url ){
  298. return !( url.indexOf( Tracker.Path.getBase(window.document) ) == 0 );
  299. },
  300. intelligentGet: function( url ){
  301. url = Tracker.Path.merge( Tracker.Path.getBase(window.document), url );
  302. return Tracker.Util.isCrossDomain( url ) ? RemoteProxy.request( url ) : Tracker.Util.request( url );
  303. },
  304. request: function( url, charset ){
  305. var xhr, pm, timeout, timer, timeStart, timeConsum;
  306. pm = new Tracker.Promise();
  307. timeout = 10e3;
  308. if( XMLHttpRequest )
  309. xhr = new XMLHttpRequest();
  310. else
  311. xhr = new ActiveXObject( "Microsoft.XMLHTTP" );
  312. xhr.open( "GET", url, true );
  313. if( charset && xhr.overrideMimeType )
  314. xhr.overrideMimeType( "text/html;charset=" + charset );
  315. xhr.onreadystatechange = function(){
  316. if( xhr.readyState == 4 && xhr.status == 200 ){
  317. clearTimeout( timer );
  318. timeConsum = Tracker.Util.time();
  319. pm.resolve( {
  320. response: xhr.responseText,
  321. consum: timeConsum - timeStart
  322. } );
  323. xhr = null;
  324. }
  325. };
  326. timer = setTimeout( function(){
  327. xhr.abort();
  328. pm.reject();
  329. xhr = null;
  330. }, timeout );
  331. timeStart = Tracker.Util.time();
  332. xhr.send( null );
  333. return pm;
  334. },
  335. delay: function (){
  336. // single thread
  337. var tasks, start, timer, task;
  338. tasks = [];
  339. start = function(){
  340. clearInterval( timer );
  341. timer = setInterval( function(){
  342. if( tasks.length ){
  343. task = tasks.shift();
  344. task.apply();
  345. }else{
  346. clearInterval( timer );
  347. }
  348. }, 1e2 );
  349. };
  350. return function( fn ){
  351. tasks.push( fn );
  352. start();
  353. }
  354. }(),
  355. onCpuFree: function( fn, process ){
  356. var now, start, last, count, d, timer, limit, times, space;
  357. start = last = Tracker.Util.time();
  358. count = 0;
  359. times = 30;
  360. space = 20;
  361. limit = 100;
  362. process = process || Tracker.Util.blank;
  363. timer = setInterval( function(){
  364. now = Tracker.Util.time();
  365. if( ( d = now - last ) < limit && ++ count == times ){
  366. clearInterval( timer );
  367. return fn();
  368. }else if( d > limit ){
  369. count = 0;
  370. }
  371. process( ( last = now ) - start );
  372. }, space );
  373. }
  374. }
  375. }();