1/* 2 * jQury Utils plugin 3 * 4 * The MIT License 5 * 6 * Copyright (c) 2012- Shoji Matsumoto ([email protected]) 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a copy 9 * of this software and associated documentation files (the "Software"), to deal 10 * in the Software without restriction, including without limitation the rights 11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 * copies of the Software, and to permit persons to whom the Software is 13 * furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included in 16 * all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 * THE SOFTWARE. 25 * 26 ********************************************************************* 27 * 28 * This is a jQuery plugin includes some useful small functions. 29 * 30 * $.typeOf() : better 'typeof' 31 * -> 'null','undefined','boolean','string','number','function','date','regexp','object' 32 * 33 * var bound_func = $.closure([arg1,arg2,...],thisObj,function(_binded_arg1,_binded_arg2,..., arg1,arg2){}); 34 * bound_func(arg2, arg2); 35 * 36 * $.doLater(function(){...},delay).then(function(){success}).fail(function(ex){...}; 37 * $.doLaterWith([arg1,arg2,...],thisObj,function(_arg1,_arg2,...){...},delay).then(function(){success}).fail(function(ex){...}; 38 * 39 * $.resolve({a:{b:"resolved a.b value"}},"a.b") 40 * -> "resolved a.b 41 * var obj = {a:{b:"value"}}; 42 * $.resolve(obj, "b", "modified value for a.b"); 43 * 44 * $.parseISO8601('1970-01-01T00:00:00Z') 45 * -> Date(0) 46 * 47 * $.dateformat(new Date(0), 'yyyy/MM/dd HH:mm') 48 * -> "1970/01/01 00:00" 49 * 50 * $.numformat.comma3(1234.5678) -> '1,234.567' 51 * 52 * $.numformat.round(12345, 3) -> 12300 53 * $.numformat.round(12345.678, -1, true) -> 12345.600 54 * 55 * $.numformat.kilo(1024) -> 1 56 * $.numformat.mega(1024*1024) -> 1 57 * 58 * $.encodeHtml('test<a>test') -> 'test<a>test' 59 * $.decodeHtml('text&text') -> 'text&text' 60 * 61 * $.relativeTime(new Date()) -> 'Now', 'xxx min later', ... 62 * 63 * $.calcAge('2000-01-01') -> 12 (age for person birthed at '1950-01-01' as int) 64 * 65 */ 66 67(function($) { 68 69 // useful polyfills Array.from / array.includes / array.fill 70 // (*) every,filter,forEach,map,reduce,some are already supported by IE9+/Edge 71 !function(A,P,U){ 72 A.from=A.from||function(a,f,t){var r=P.slice.apply(a);return f?r.map(f.bind(t)):r}; 73 P.includes||Object.defineProperty(P,'includes',{value:function(e,i){return this.slice(i===U?0:i).indexOf(e)>=0}}); 74 P.fill||Object.defineProperty(P,'fill',{value:function(v,s,e){var i,l=this.length;s=(s===U?0:s);e=(e===U?l:e);s=(s<0?l-s:s);for(i=s;i<e;i++){this[i]=v;};return this}}); 75 }(Array,Array.prototype,undefined); 76 77 // ECMA262 WhiteSpace match <USP:Unicode Spaces> 78 // https://www.ecma-international.org/ecma-262/5.1/#sec-15.5.4.20 79 // https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/trim 80 String.prototype.trimasc = function(){ return this.replace(/(^[ \f\n\r\t\vâ\u00a0\ufeff]+|[ \f\n\r\t\vâ\u00a0\ufeff]+$)/g, '') } 81 82 var _div = $("<div>"); 83 var loremIpsum_src = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In dignissim sem et arcu imperdiet molestie. Curabitur non libero at diam eleifend molestie id ac justo. Sed viverra, est ut mattis faucibus, lacus diam cursus mauris, eu laoreet nibh augue nec ante. Vestibulum id elit sit amet velit pulvinar fermentum et egestas libero. Nullam hendrerit nunc non orci convallis at sodales sem pellentesque. Integer imperdiet porttitor faucibus. Etiam placerat ultrices venenatis. Nam lectus est, posuere at interdum non, ullamcorper sit amet augue. Integer tristique tellus ut eros fermentum molestie sollicitudin tortor molestie. Nam facilisis auctor mattis. Sed et lectus leo. Aliquam erat volutpat. In iaculis vehicula arcu, scelerisque sodales turpis vehicula vel. Quisque eleifend porttitor dolor ac fermentum. Suspendisse nec lectus vel elit euismod vestibulum. " 84 .split(' '); 85 var scrollbarWidth = null, scrollbarHeight = null; 86 87 /** 88 * extend $.brwoser for iOS, Android and add css to <body>. 89 * $.browser.{iphone,ipod,ipad} = true|false 90 * $.browser.ios.version = iOS version (ex: 5.1.1) 91 * $.browser.android 92 * $.browser.android.version = Android version (ex:2.3.4) 93 * $.browser.android.{mobile,tablet} 94 * 95 * append class to <body>: 96 * ua-{webkit,safari,msie,mozilla,opera,ios,android}, 97 * ua-{webkit,safari,msie,mozilla,opera,ios,android}-<version>, ex) ua-ios-5.1.1 98 * ua-{webkit,safari,msie,mozilla,opera,ios,android}-<version|x.x>, ex) ua-ios-5.1 99 * ua-{webkit,safari,msie,mozilla,opera,ios,android}-<version|x> ex) ua-ios-5 100 */ 101 var _ua = navigator.userAgent, m, k, i; 102 103 // $.browser = $.browser || {}; 104 $.browser = { useragent: _ua }; 105 106 // http://www.useragentstring.com/ 107 var rxs = [ 108 // key, regexp(ver), ismobile, break
109 ['webkit', /AppleWebKit\/([0-9.]+)/, false, false] 110 ,['ios', /iPhone OS ([\d_]+)/, true, false] 111 ,['ios', /iPad;(?: U;)? CPU OS ([\d_]+)/, true, false] 112 ,['macosx', /Mac OS X ([\d_]+)/, false, false] 113 ,['operamini', /Opera Mini\/([0-9.]+)$/, true, false] 114 ,['operamobi', /Opera Mobi\/([^ ;]+)$/, true, false] 115 ,['opera', /^Opera\/.*Version\/([0-9.]+)$/, false, true] 116 ,['opera', /^Opera ([0-9.]+)/, false, true] 117 ,['opera', /Opera[\/ ]([0-9.]+)/, false, true] 118 ,['chrome', /CriOS\/([0-9.]+)/, true, true] 119 ,['chrome', /Chrome\/([0-9.]+)/, false, true] 120 ,['firefox', /Fennec\/([0-9.]+)/, true, true] 121 ,['firefox', /Firefox\/([0-9.]+)/, false, true] 122 ,['safari', /Version\/([0-9.]+) Safari\/([0-9.]+)/, false, true] 123 ,['safari', /Safari\/([0-9.]+)/, false, true] 124 ,['msie', /IEMobile\/([0-9.]+)/, true, true] 125 ,['msie', /MSIE ([0-9.]+)/, false, true] 126 ]; 127 $.each(rxs, function(i, v){ 128 var k = v[0]; 129 var m = _ua.match(v[1]); 130 if (m) { 131 $.browser[k] = { 132 version: m[1].replace(/_/g, '.'), 133 mobile: v[2] 134 }; 135 $.browser.version = $.browser[k].version; 136 $.browser.mobile = v[2]; 137 if (v[3]) { 138 return false; 139 } 140 } 141 }); 142 143 if ($.browser.opera) { 144 m = _ua.match(/Opera Mini\/([0-9.]+)/); 145 if (m) { 146 $.browser.opera.mini = { version:m[1] }; 147 $.browser.opera.mobile = true; 148 } 149 } 150 if ($.browser.safari) { 151 m = _ua.match(/ Mobile\//); 152 if (m) { 153 $.browser.safari.mobile = true; 154 } 155 } 156 if ($.browser.msie) { 157 $.browser.msie.backcompat = document.compatMode == 'BackCompat'; 158 // see http://d.hatena.ne.jp/favril/20090424/1240548931 159 } 160 161 $.browser.mozilla = $.browser.firefox; 162 163 if (m = _ua.match(/Android ([0-9.]+)/)) { 164 $.browser.android = { 165 mobile: !!_ua.match(/Mobile/), 166 tablet: !(_ua.match(/Mobile/)), 167 version: m[1] 168 }; 169 } else if (m = _ua.match(/Android;/)) { 170 $.browser.android = { 171 mobile: true, 172 firefox: true, 173 version:'unknown' 174 }; 175 } 176 177 if ($.browser.ios) { 178 $.browser.iphone = !!_ua.match(/iPhone/); 179 $.browser.ipod = !!_ua.match(/iPod/); 180 $.browser.ipad = !!_ua.match(/iPad/); 181 $.browser.ios.mobile = $.browser.iphone || $.browser.ipod; 182 $.browser.ios.tablet = $.browser.ipad; 183 } 184 185 $.browser.mobile = $.browser.iphone || $.browser.ipod 186 || ($.browser.android && $.browser.android.mobile) 187 || ($.browser.msie && $.browser.msie.mobile) 188 || ($.browser.firefox && $.browser.firefox.mobile); 189 $.browser.tablet = $.browser.ipad || ($.browser.android && $.browser.android.tablet); 190 $.browser.desktop = !$.browser.mobile && !$.browser.tablet; 191 $.browser.touchable = !!('ontouchstart' in window); 192 193 $.each(['msie', 'webkit', 'safari', 'opera', 'mozilla', 'firefox', 'chrome', 'opera'], function(i, v){ 194 var _b = $.browser[v]; 195 if (_b){ 196 $('html').addClass('ua-' + v); 197 var _v = (_b.version || $.browser.version).split('.'); 198 if (_v) { 199 $('html') 200 .addClass('ua-' + v + '-' + _v.join('.')) 201 .addClass('ua-' + v + '-' + _v[0] + '.' + _v[1]) 202 .addClass('ua-' + v + '-' + _v[0]); 203 } 204 } 205 }); 206 207 $.each($.browser, function(k, v){ 208 if (!v) { 209 delete $.browser[k]; 210 } 211 }); 212 213 $.each(['ios', 'android'], function(i, v){ 214 var _b = $.browser[v]; 215 if (_b){ 216 $('html').addClass('ua-' + v); 217 var _v = $.browser[v].version.split('.'); 218 if (_v) { 219 $('html') 220 .addClass('ua-' + v + '-' + _v.join('.')) 221 .addClass('ua-' + v + '-' + _v[0] + '.' + _v[1]) 222 .addClass('ua-' + v + '-' + _v[0]); 223 } 224 } 225 }); 226 227 // CSSã®å°æ°ç¹ä¸¸ã 228 // http://iwb.jp/decimal-point/ 229 $.browser.cssRound = function(v){ 230 return Math.round(v); 231 }; 232 if ($.browser.webkit) { 233 $.browser.cssRound = function(v) { 234 return Math.floor(v + 0.01); 235 }; 236 } else if ($.browser.firefox) { 237 $.browser.cssRound = function(v) { 238 return Math.floor(v + (1 - 0.49166)); 239 }; 240 } else if ($.browser.msie) { 241 $.browser.cssRound = function(v) { 242 return Math.floor(v); 243 }; 244 } 245 246 /* 247 $.each(['mobile', 'tablet', 'desktop'], function(i, v){ 248 $('body').toggleClass('ua-' + v, $.browser[v]); 249 }); 250 */ 251 252 253 if (!('console' in window)) { 254 window.console = { log:$.noop, error:$.noop, warn:$.noop, info:$.noop }; 255 } else if (typeof window.console.log != 'function') { 256 // for IE 257 var _console = window.console; 258 window.console = {}; 259 $.each(['log', 'error', 'warn', 'info'], function(i, v){ 260 (function(method){ 261 var org = _console[method]; 262 window.console[method] = function(){ 263 return org(Array.prototype.slice.apply(arguments).join(', ')); 264 }; 265 })(v); 266 }); 267 } 268 269 $(document).ready(function(){ 270 var $div = $('#_dpi') || $('<div>').attr('id', '_dpi').css({ 271 position: 'absolute', 272 width: '1in', 273 height: '0', 274 padding: 0 275 }).appendTo('body'); 276 $.browser.dpi = $div.width(); 277 }); 278 279 $(document).ready(function(){ 280 var dummy_console = $('textarea#console'); 281 if (dummy_console[0]){ 282 var dump = function(){ 283 var args = Array.prototype.slice.apply(arguments); 284 return $.map(args, function(v){ 285 if (v === window) return '[Window]'; 286 // if (v instanceof jQuery) return '[jQuery:[' + v.map(function(i, v){return dumpHTMLElement(v);}).toArray().join(',') + ']]'; 287 if ($.isXMLDoc(v)) return '[Node:' + dumpHTMLElement(v) + ']'; 288 if ($.isPlainObject) return ($.toJSON ? $.toJSON(v) : ''+v ); 289 return "" + v; 290 }).join(','); 291 }; 292 $.each([['log',''], ['error','\nERR: '], ['warn','WARN: '], ['info', 'INFO: ']], function(i, v){ 293 (function(method){ 294 var lead = method[1], method = method[0], org = window.console[method]; 295 window.console[method] = function(){ 296 var args = Array.prototype.slice.apply(arguments); 297 dummy_console.val(dummy_console.val() + lead + dump.apply(this, args) + '\n').scrollTop(100000); 298 return org.apply(console, arguments); 299 }; 300 })(v); 301 }); 302 console.log('--- start console ---'); 303 } 304 }); 305 306 307 $.extend({ 308 309 _log : function() { 310 if ('console' in window) { 311 console.log.apply(console, arguments); 312 } 313 }, 314 315 _error : function() { 316 if ('console' in window) { 317 console.error.apply(console, [(new Error()).stack].concat(arguments)); 318 } 319 }, 320 321 _typeOf_constructors : { 322 array : (new Array()).constructor, 323 date : (new Date()).constructor,
324 regexp : (new RegExp()).constructor, 325 string : (new String()).constructor, 326 number : (new Number()).constructor, 327 boolean : (new Boolean()).constructor 328 }, 329 330 typeOf : function(v) { 331 /** 332 * return better 'typeof' / jQuery 1,2 compat 333 */ 334 if (v === null) { 335 return 'null'; 336 } 337 if (typeof v !== 'object') { 338 return typeof v; 339 } 340 var typeString = Object.prototype.toString.call(v); 341 var typeMap = { 342 '[object Array]': 'array', 343 '[object Date]': 'date', 344 '[object RegExp]': 'regexp', 345 '[object Function]': 'function', 346 '[object Arguments]': 'arguments', 347 '[object Error]': 'error', 348 '[object Boolean]': 'boolean', 349 '[object Number]': 'number', 350 '[object String]': 'string', 351 '[object Map]': 'map', 352 '[object Set]': 'set', 353 '[object WeakMap]': 'weakmap', 354 '[object WeakSet]': 'weakset', 355 '[object ArrayBuffer]': 'arraybuffer', 356 '[object DataView]': 'dataview', 357 '[object Int8Array]': 'int8array', 358 '[object Uint8Array]': 'uint8array', 359 '[object Uint8ClampedArray]': 'uint8clampedarray', 360 '[object Int16Array]': 'int16array', 361 '[object Uint16Array]': 'uint16array', 362 '[object Int32Array]': 'int32array', 363 '[object Uint32Array]': 'uint32array', 364 '[object Float32Array]': 'float32array', 365 '[object Float64Array]': 'float64array' 366 }; 367 368 return typeMap[typeString] || 'object'; 369 }, 370 371 min : function(){ 372 /** 373 * return minimum argument value (for number, string, Date) 374 */ 375 var ret = arguments[0]; 376 Array.prototype.forEach.call(arguments, function(v){ 377 if (v === undefined || v === null) { return; } 378 if (ret > v) { ret = v; } 379 }); 380 return ret; 381 }, 382 383 max : function(){ 384 /** 385 * return maximum argument value (for number, string, Date) 386 * ignore null, undefined 387 */ 388 var ret = arguments[0]; 389 Array.prototype.forEach.call(arguments, function(v){ 390 if (v === undefined || v === null) { return; } 391 if (ret < v) { ret = v; } 392 }); 393 return ret; 394 }, 395 396 isDeferred : function(obj) { 397 return obj && obj.then && obj.fail && typeof obj.always === 'function'; 398 }, 399 400 closure : function(args, thisobj, func) { 401 /** 402 * make args binded closure for func. 403 * func is called with arg(args[0], args[1], ... , arguments[0], arguments[1]. 404 * ex) 405 * var f2 = $.closure([1,2], null, function(_a, _b, c) { print _a,_b,c; }); 406 * f2(3); -> 1,2,3 407 * 408 * @param args 409 * array of binding arguments 410 * @param thisobj 411 * binding 'this' object 412 * @param func 413 * closure function 414 * @return args and 'this' binded function 415 */ 416 var _args = Array.prototype.slice.call(args); 417 return function() { 418 return func.apply(thisobj, _args.concat(Array.prototype.slice.apply(arguments))); 419 }; 420 }, 421 422 doLaterWith : function(args, thisobj, func, delay) { 423 /** 424 * Deferred setTimeout with closure 425 */ 426 delay = (delay === undefined) ? 0 : delay; 427 var c = $.closure(args, thisobj, func); 428 return $.Deferred(function(_d) { 429 setTimeout(function() { 430 try { 431 _d.resolve(c()); 432 } catch (ex) { 433 _d.reject(ex); 434 throw ex; 435 } 436 }, delay); 437 }); 438 }, 439 440 doLater : function(func, delay) { 441 /** 442 * Deferred setTimeout 443 */ 444 if (typeof func == 'function') { 445 return $.doLaterWith([], null, func, delay); 446 } else { 447 return $.doLaterWith([], null, function() { 448 }, func, 1); 449 } 450 }, 451 452 pollWith : function(args, thisobj, func, timeout, interval) { 453 /** 454 * while func returns true, func is called repeatedly by interval 455 */ 456 interval = (interval === undefined) ? 250 : interval; 457 timeout = (timeout == undefined) ? -1 : timeout; 458 var c = $.closure(args, thisobj, func), remain = timeout * 1000 / interval; 459 return $.Deferred($.closure([timeout, remain, interval], null, function(timeout, remain, interval, _d){ 460 var ret, _t = null; 461 if ((ret = c()) !== true) { 462 _d.resolve(ret); 463 } else { 464 _t = setInterval(function(){ 465 if (timeout > 0 && remain < 0) { 466 clearInterval(_t); 467 _d.resolve('timeout'); 468 } else if ((ret = c()) !== true) { 469 clearInterval(_t); 470 _d.resolve(ret); 471 } 472 remain--; 473 }, interval); 474 } 475 })); 476 }, 477 478 poll : function(func, timeout, interval) { 479 return $.pollWith([], null, func, timeout, interval); 480 }, 481 482 resolve : function(obj, str, val) { 483 /** 484 * resolve object by string. 485 * ex) 486 * $.resolve(obj, 'var'); -> obj.var 487 * $.resolve(obj, 'arr[10]'); -> obj.arr[10] 488 * $.resolve(obj, 'func()'); -> obj.func() 489 * $.resolve(obj, 'var.func()'); -> obj.var.func() 490 * $.resolve(obj, 'var.arr[1]'); -> obj.var.arr[1] 491 * $.resolve(obj, 'func()[10]'); -> obj 492 */ 493 494 var bits = str.split('.'), bit, settable = false;
495 var curobj = obj; 496 var curname = ''; 497 while (bit = bits.shift()) { 498 499 if (curobj === undefined) { 500 throw new Error('ResolveError: obj is undefined:<obj>' + curname); 501 } 502 503 curname = curname + '.' + bit; 504 var res = bit.match(/^([a-zA-Z0-9_]+)(\(\))?(\[(\d+)\])?/); 505 506 var name = res[1]; 507 var isfunc = res[2] == '()'; 508 var isarray = (res[3] != undefined) && (res[3] != ''); // '' 509 // for 510 // IE7 511 var arraynum = parseInt(res[4], 10); 512 513 if (isfunc || isarray) { 514 if (curobj[name] === undefined) { 515 throw new Error('ResolveError: property is undefined:<obj>' + curname); 516 } 517 if (isfunc) { 518 settable = false; 519 if (curobj[name].call === undefined) { 520 throw new Error('ResolveError:property is not callable:<obj>' + curname); 521 } 522 curobj = curobj[name].call(curobj); 523 } else { 524 settable = true; 525 if (curobj[name] === undefined) { 526 throw new Error('ResolveError:undefined property:<obj>' + curname); 527 } 528 curobj = curobj[name][arraynum]; 529 } 530 } else { 531 settable = true; 532 curobj = curobj[name]; 533 } 534 } 535 536 if (val !== undefined) { 537 if (settable) { 538 eval('(function(obj,v){obj.' + str + ' = v;})(obj,val)'); 539 } 540 } 541 542 return curobj; 543 544 }, 545 546 lpad : function(chr, len, str, do_cut){ 547 /** 548 * padding <chr> character to left of str to length <len>. 549 * if do_cut = true, force cut over length. 550 * ex) 551 * lpad('0', 4, '321') => '0321' 552 * lpad(' ', 3, 'a') => ' a' 553 * lpad(' ', 3, 'abcd') => 'abcd' 554 * lpad(' ', 3, 'abcd', true) => 'bcd' 555 */ 556 if (!do_cut && str.length >= len) { return str; } 557 return (Array.apply(null, Array(len)).map(function(){ return chr; }).join('') + str).splice(-len); 558 }, 559 560 parseISO8601 : function(str) { 561 /** 562 * parse ISO8601 "YYYY-MM-DDTHH:MM:SS+TTTT" to Date(). 563 */ 564 var p = str.match(/(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?T(\d{2})(?::(\d{2})(?::(\d{2})(?:\.(\d+))?)?)(Z|([+-]\d{2})(?::?(\d{2}))?)/); 565 if (p === null) { 566 throw new Error('ISO8601ParseError', 'Invalid ISO8601 DateTime : ' + str); 567 } 568 for ( var i = 0; i < p.length; i++) { 569 switch (i) { 570 case 2: 571 case 3: 572 if (p[i] === undefined) { 573 p[i] = '01'; 574 } 575 ; 576 break; 577 case 4: 578 case 5: 579 case 6: 580 case 7: 581 case 9: 582 case 10: 583 if (p[i] === undefined) { 584 p[i] = '00'; 585 } 586 ; 587 break; 588 case 8: 589 if (p[i] === 'Z') { 590 p[9] = '+00'; 591 } 592 ; 593 break; 594 } 595 } 596 return new Date(Date.parse([ p[1], p[2], p[3] ].join('/') + ' ' + [ p[4], p[5], p[6] ].join(':') + ' GMT' + [ p[9], p[10] ].join(''))); 597 }, 598 599 toISO8601 : function(date) { 600 /** 601 * Date() to ISO8601 string. 602 * need jquery-json.js 603 */ 604 return $.toJSON(date).replace(/"/g, ''); 605 }, 606 607 dateformat : function(date, format, to_utc) { 608 /** 609 * format Date() with dateformat (Java SimpleDateFormat()) 610 * 611 * @param date 612 * Date() 613 * @param format 614 * dateformat string. supported: YymndjHGisShgaA. default - 615 * yyyy/M/d h:mm 616 */ 617 618 if (! date instanceof Date) { 619 console.error('dateformat:date is not Date', date); 620 return 'Invalid Date'; 621 } 622 623 if (isNaN(date.getTime())) { 624 return 'Invalid Date'; 625 } 626 627 to_utc = (to_utc === undefined) ? false : true; 628 format = (format === undefined) ? 'yyyy/M/d h:mm' : format; 629 function pad0(num, len) { 630 return ('000000' + num).split('').reverse().splice(0, len).reverse().join(''); 631 } 632 var dt = date, y, M, d, H, m, s, S; 633 if (to_utc) { 634 y = dt.getUTCFullYear(); 635 M = dt.getUTCMonth() + 1; 636 d = dt.getUTCDate(); 637 H = dt.getUTCHours(); 638 m = dt.getUTCMinutes(); 639 s = dt.getUTCSeconds(); 640 } else { 641 y = dt.getFullYear(); 642 M = dt.getMonth() + 1; 643 d = dt.getDate(); 644 H = dt.getHours(); 645 m = dt.getMinutes(); 646 s = dt.getSeconds(); 647 } 648 S = dt.getMilliseconds(); 649 650 var formatted = { 651 yyyy : y, 652 yy : (y + '').substring(2, 4), // year 653 MM : pad0(M, 2), 654 M : M, // month 655 dd : pad0(d, 2), 656 d : d, // day 657 HH : pad0(H, 2), 658 H : H, // hour 659 mm : pad0(m, 2), // min 660 m : m, 661 ss : pad0(s, 2), // sec 662 s : s, 663 SSS : pad0(S, 3), // msec 664 KK : pad0(H % 12, 2), 665 K : H % 12, 666 hh : pad0((H % 12) == 0 ? 12 : (H % 12), 2), 667 h : (H % 12) == 0 ? 12 : (H % 12), 668 a : H < 12 ? 'AM' : 'PM' 669 }; 670 var ret = [], bit, bits = format.split("'"); 671 while (bits.length) { 672 bit = bits.shift(); 673 if (bit == '') {
674 ret.push('\''); 675 } else { 676 ret.push(bit.replace(/(yyyy|yy|[MdhHmsK]{1,2}|S{1,3}|a)/g, function(m0, m1, m2, idx) { 677 return formatted[m1]; 678 })); 679 } 680 bit = bits.shift(); 681 if (bits.length) { 682 ret.push(bit); 683 } 684 } 685 return ret.join(''); 686 }, 687 688 dateCalc : function(base_date, delta_str) { 689 /** 690 * calcurate Date(). 691 * ex) 692 * $.dateCalc(new Date(), '+1d'); 693 * $.dateCalc(new Date(), '-1y-1d'); 694 * $.dateCalc(new Date(), '+24h'); 695 * 696 * @param base_date Date() 697 * @param delta_str string delta from base_date. 698 * format : [+-]\d+[yMdHms] 699 * ex) '+1d' : after 1day, '-1d' before 1day, '1y, 1M' after 1 year and 1day 700 * @return Date() from base_date + delta_str 701 */ 702 var m = delta_str.match(/([-+]?\d+[yMdHms],?\s*)/g); 703 if (m === null) { 704 throw new Error('invalid delta_str: ' + delta_str); 705 } 706 var d = {'y' : 0, 'M' : 0, 'd' : 0, 'H' : 0, 'm' : 0, 's' : 0}; 707 $.each(m, function(i, v){ 708 var n = v.match(/^([-+]?\d+)([yMdHms])$/); 709 d[n[2]] = parseInt(n[1], 10); 710 }); 711 return new Date(base_date.getFullYear()+d.y, base_date.getMonth()+d.M, base_date.getDate()+d.d, base_date.getHours()+d.H, base_date.getMinutes()+d.m, base_date.getSeconds()+d.s); 712 }, 713 714 relativeTime : function(date, options) { 715 /** 716 * return relative time string. 717 * @param date Date() 718 * @param options { 719 * now : <Date() : origin>, 720 * dateformat : 'yyyy/M/d H:MM', 721 * thresholds : [ [<min in seconds>, <duration in secons>, '<suffix string>'], 722 * suffixes : [ '<ago string>', '<later string>'] 723 * } 724 */ 725 options = $.extend({ 726 now : new Date(), 727 dateformat : 'yyyy/M/d H:MM', 728 thresholds : [ [ 10, 0, 'Now' ], [ 60, 1, ' sec' ], [ 60 * 60, 60, ' min' ], [ 2 * 60 * 60, 60 * 60, ' hour' ], 729 [ 24 * 60 * 60, 60 * 60, ' hours' ], [ 2 * 24 * 60 * 60, 24 * 60 * 60, ' day' ], [ 30 * 24 * 60 * 60, 24 * 60 * 60, ' days' ] ], 730 suffixes : [ ' ago', ' later' ] 731 }, options); 732 var suffix = (options.now.getTime() + 100 > date.getTime()) ? options.suffixes[0] : options.suffixes[1]; 733 var delta = Math.floor(Math.abs((options.now.getTime() - date.getTime()) / 1000)); 734 for ( var i = 0, l = options.thresholds.length; i < l; i++) { 735 var th = options.thresholds[i]; 736 if (delta < th[0]) { 737 if (th[1] > 0) { 738 return Math.max(1, Math.floor(delta / th[1])) + th[2] + suffix; 739 } else { 740 return th[2]; 741 } 742 } 743 } 744 return $.dateformat(date, options.dateformat); 745 }, 746 747 calcAge : function(birthday_str) { 748 /** 749 * calc age 750 * @param birthday_str 'yyyy-MM-dd' 751 * @return age int() 752 */ 753 var _birth = parseInt(birthday_str.replace(/[-\/]/g, '')); 754 var _today = parseInt($.dateformat(new Date(), 'yyyyMMdd')); 755 return parseInt((_today - _birth) / 10000); 756 }, 757 758 numformat : { 759 comma3 : function(v) { 760 /** 761 * return 'comma formatted string' of number 762 */ 763 if (!isFinite(v) || isNaN(v)) { 764 return v; 765 } 766 if (v < 1000 && v > -1000) { 767 return new String(v); 768 } 769 v = (new String(v)).match(/^([-+]?)(\d+)(\.\d+)?$/); 770 v[2] = v[2].replace(/\B(?=(?:\d{3})+(?!\d))/g, ','); 771 v[3] = v[3] === undefined ? '' : v[3]; 772 return v[1] + v[2] + v[3]; 773 }, 774 round : function(v, pos, pad0) { 775 /** 776 * return rounded number. 777 * @param pos round position ( 0=1, 1=10, 2=100, -1=0.1, -2=0.01 ) 778 * @param pad0 padding 0 for decimal points 779 */ 780 pad0 = (pad0 === undefined) ? true : pad0; 781 pos = (pos === undefined) ? 0 : pos; 782 var ret = v; 783 if (pos < 0) { 784 ret = Math.round(v * Math.pow(10, -pos)) / Math.pow(10, -pos); 785 } else { 786 ret = Math.round(v / Math.pow(10, pos)) * Math.pow(10, pos); 787 } 788 if (pad0 && pos < 0) { 789 ret = ret.toFixed(-pos); 790 } 791 return ret; 792 }, 793 kilo : function(v, use_si) { 794 /** 795 * return kilo value of v (1024 = 1k) 796 * @param use_si : use 1000 = 1K 797 */ 798 return $.numformat.round(v / (use_si?1000:1024), -2, false); 799 }, 800 mega : function(v, use_si) { 801 /** 802 * return mega value of v (1024*1024 = 1Mi) 803 * @param use_si : 1M = 1000*1000 804 */ 805 return $.numformat.round(v / (use_si?1000*1000:1024*1024), -2, false); 806 }, 807 tera : function(v, use_si) { 808 /** 809 * return mega value of v (1024*1024*1024 = 1Ti) 810 * @param use_si : 1T = 1000*1000*1000 811 */ 812 return $.numformat.round(v / (use_si?1000*1000*1000:1024*1024*1024), -2, false); 813 }, 814 shorten : function(v, use_si) { 815 /** 816 * return auto formatted value 817 */ 818 var a = Math.abs(v), n = v < 0 ? -1 : 1, 819 u = use_si ? 1000 : 1024, 820 r; 821 if (a < u) { 822 r = $.numformat.round(a, -2, false); 823 s = ''; 824 } else if (a < u*u) { 825 r = $.numformat.kilo(a, use_si); 826 s = use_si ? 'k' : 'Ki'; 827 } else if (a < u*u*u) { 828 r = $.numformat.mega(a, use_si); 829 s = use_si ? 'M' : 'Mi'; 830 } else { 831 r = $.numformat.tera(a, use_si); 832 s = use_si ? 'T' : 'Ti'; 833 } 834 if (r < 10) { 835 836 } if (r < 100) { 837 r = $.numformat.round(r, -1, true); 838 } else { 839 r = $.numformat.round(r, 0, true); 840 } 841 842 r = (r * n) + s; 843 return r; 844 } 845 }, 846 847 cookie : function(key, val, options) { 848 /** 849 * get/set cookie (expect uri encoding) 850 * @param key key 851 * @param val value 852 * @param options { 853 * expires : <Date()> | <days:number> | 'never', 854 * path : '<path>',
855 * domain : '<domain>', 856 * secure : <false|true> 857 * } 858 */ 859 if (arguments.length <= 1) { 860 var cookies = {}, bit, bits = document.cookie.split('; '); 861 while (bit = bits.shift()) { 862 bit = bit.split('='); 863 try { 864 cookies[decodeURIComponent(bit[0])] = decodeURIComponent(bit[1] || ''); 865 } catch(ex) { 866 console.error('$.cookie: unexpecedly encoded:' + bit[0] + '=' + bit[1]); 867 cookies[bit[0]] = bit[1]; 868 } 869 } 870 if (key !== undefined) { 871 return cookies[key]; 872 } 873 return cookies; 874 } else { 875 // delete cookie 876 options = $.extend({ 877 expires : '', 878 maxAge : null, 879 path : '', 880 domain : '', 881 secure : false 882 }, options); 883 if (val === null) { 884 val = ''; 885 options.expires = new Date(0); 886 options.maxAge = 0; 887 console.log('$.cookie:will delete:' + key); 888 } else { 889 if ($.typeOf(key) != 'string'){ 890 throw new Error('$.cookie:key is not string.'); 891 } 892 if ($.typeOf(val) != 'string' && $.typeOf(val) != 'number') { 893 throw new Error('$.cookie:value is not string: ' + $.typeOf(val)); 894 } 895 } 896 if (options.maxAge) { 897 var expires = new Date(); 898 expires.setTime(new Date().getTime() + options.maxAge * 1000); 899 options.expires = expires; 900 } 901 902 if (options.expires) { 903 if (options.expires === 'never') { 904 // var t = new Date('2038-01-19T04:14Z');/* max epoch : 2038-01-19T04:14:07.999Z */ 905 options.expires = 365*10; 906 } 907 if (typeof options.expires === 'number') { 908 var days = options.expires, t = options.expires = new Date(); 909 t.setTime(+t + days * 864e+5); 910 } 911 if (!options.expires instanceof Date) { 912 console.error('$.cookie: expires is not Date() : ' + key); 913 } 914 } 915 console.log('$.cookie:will set:' + key + '=' + val, options); 916 var ret = document.cookie = [ 917 encodeURIComponent(key) + '=' + encodeURIComponent(val), 918 // options.expires ? ('; expires=' + options.expires.toUTCString()) : '', /* 鿍奍 */ 919 options.expires ? ('; max-age=' + Math.round((options.expires.getTime() - new Date().getTime())/1000)) : '', 920 options.path ? ('; path=' + options.path) : '', 921 options.domain ? ('; domain=' + options.domain) : '', 922 options.secure ? '; secure' : '' ].join(''); 923 console.log('$.cookie:result:' + key + '=' + $.cookie(key)); 924 return ret; 925 } 926 927 }, 928 929 encodeHtml : function(text) { 930 return _div.text(text).html(); 931 }, 932 933 decodeHtml : function(html) { 934 return _div.html(html).text(); 935 }, 936 937 anchor : function(val, skip) { 938 var fn = arguments.callee; 939 switch (typeof val) { 940 // getter 941 case "undefined": 942 var ret = location.hash; 943 if (!ret) { 944 return null; 945 } 946 ret = ret.replace(/^#/, ""); 947 return $.browser.fx ? ret : decodeURIComponent(ret); 948 // callback 949 case "function": 950 if (!fn.tid) { 951 fn.hash = location.hash; 952 (function rec() { 953 if (!fn.skip && fn.hash !== location.hash) { 954 fn.hash = location.hash; 955 $(window).trigger("changeAnchor", $.anchor()); 956 } 957 fn.tid = setTimeout(rec, 300); 958 })(); 959 } 960 return $(window).bind("changeAnchor", val); 961 // setter 962 default: 963 if (skip) { 964 fn.skip = true; 965 location.hash = encodeURIComponent(val); 966 fn.hash = location.hash; 967 fn.skip = false; 968 } else { 969 location.hash = encodeURIComponent(val); 970 } 971 return; 972 } 973 }, 974 975 loremIpsum : function(min_words, max_words) { 976 /** 977 * make loremIpsum strings. 978 */ 979 min_words = (min_words === undefined) ? 5 : min_words; 980 max_words = (max_words === undefined) ? 20 : max_words; 981 var ret = []; 982 var words_count = min_words + Math.floor(Math.random() * (max_words - max_words)); 983 for ( var i = 0; i < min_words; i++) { 984 ret.push(loremIpsum_src[Math.round(Math.random() * loremIpsum_src.length)]); 985 } 986 for (i = min_words; i < words_count; i++) { 987 ret.push(loremIpsum_src[Math.round(Math.random() * loremIpsum_src.length)]); 988 } 989 return ret.join(' '); 990 }, 991 992 loadCss : function(href, flag) { 993 /** 994 * load css file. 995 * @param href url 996 * @parm flag <true|false> load or unload 997 * @return loaded '<link>' element. 998 */ 999 if (flag == false) { 1000 return $.unloadCss(href); 1001 return; 1002 } 1003 if ($('head link[href="' + href + '"][rel="stylesheet"]')[0]) { 1004 return; 1005 } 1006 $('head').append('<link>'); 1007 var css = $('head').children(':last'); 1008 css.attr({ 1009 'href' : href, 1010 'rel' : 'stylesheet' 1011 }); 1012 return $('head').children(':last'); 1013 }, 1014 1015 unloadCss : function(elem) { 1016 /** 1017 * unload <link> element. 1018 */ 1019 if ($.typeOf(elem) === 'string') { 1020 elem = $('head link[rel="stylesheet"][href="' + elem + '"]'); 1021 } 1022 elem.remove(); 1023 }, 1024 1025 setStyle : function(style, id) { 1026 /** 1027 * add or set <style> in <head> 1028 * ex) 1029 * var $style_elm = $.setStyle('body .someclass { display:none; }'); 1030 * @param style string 1031 * @param id id for <style> 1032 * @return <style> element 1033 */ 1034 1035 if (! id === undefined ) { 1036 if (!$('#'+id).is('style')) { 1037 console.error('$.setStyle:#' + id + ' is not <style>.' ); 1038 return $(); 1039 } 1040 } 1041 var cnt = $.setStyle._cnt = ($.setStyle._cnt || 0) + 1, id = id || 'setstyle-' + cnt; 1042 var $new = $('<style id="' + id + '">' + style + '</style>'); 1043 var $exists = $('#' + id); 1044 if ($exists[0]) { 1045 $exists.removeAttr('id'); 1046 $new.insertAfter($exists); 1047 $exists.remove(); 1048 } else { 1049 $new.appendTo($('head')); 1050 } 1051 return $new; 1052 }, 1053 1054 removeStyle : function(target) { 1055 /** 1056 * remove <style> in <head>
1056 generated with $.setStyle 1057 * ex) 1058 * $.setStyle('.elm { property:value; }', 'mystyleid'); 1059 * $.removeStyle('mystyleid'); 1060 * 1061 * var $style = $.setStyle(...); 1062 * $.removeStyle($style); 1063 * 1064 * 1065 */ 1066 if (! id_or_$style_elm instanceof $) { 1067 id_or_$style_elm = $('#' + id_or_$style_elm); 1068 } 1069 if (id_or_$style_elm.is('style')) { 1070 id_or_$style_elm.remove(); 1071 } 1072 }, 1073 1074 getScrollbarWidth : function(){ 1075 if (scrollbarWidth !== null) { 1076 return scrollbarWidth; 1077 } 1078 var div = $('<div>').css({ 1079 position: 'absolute', 1080 top: '-100px', 1081 left: '-100px', 1082 width: '100px', 1083 height: '100px', 1084 overflowY: 'scroll' 1085 }).appendTo('body'); 1086 scrollbarWidth = 100 - div[0].clientWidth; 1087 div.remove(); 1088 return scrollbarWidth; 1089 }, 1090 1091 getScrollbarHeight : function(){ 1092 if (scrollbarHeight !== null) { 1093 return scrollbarHeight; 1094 } 1095 var div = $('<div>').css({ 1096 position: 'absolute', 1097 top: '-100px', 1098 left: '-100px', 1099 width: '100px', 1100 height: '100px', 1101 overflowX: 'scroll' 1102 }).appendTo('body'); 1103 scrollbarHeight = 100 - div[0].clientHeight; 1104 div.remove(); 1105 return scrollbarHeight; 1106 }, 1107 1108 redraw : function(func){ 1109 $('body').redraw(func); 1110 }, 1111 1112 arrayMap : function(array, key, ignore_null) { 1113 ignore_null = ignore_null === undefined ? true : ignore_null; 1114 var ret = {}; 1115 $.each(array, function(i, v){ 1116 if (ignore_null && v == null) { 1117 return; 1118 } 1119 if (key in v) { 1120 ret[v[key]] = v; 1121 } else { 1122 throw 'arrayMap():object array[' + i + '] is not have "' + key + '"'; 1123 return false; 1124 } 1125 }); 1126 return ret; 1127 }, 1128 1129 fontAvailable : function(fontName, teststr) { 1130 var width, height; 1131 // prepare element, and append to DOM 1132 var element = $('#_fontavailable'); 1133 if (!element[0]) { 1134 element = $(document.createElement('span')).attr('id', '_fontavailable').css({ 1135 'visibility': 'hidden', 1136 'position': 'absolute', 1137 'top': '-10000px', 1138 'left': '-10000px' 1139 }).html('abcdefghijklmnopqrstuvwxyz' + (teststr || '')).appendTo(document.body); 1140 } 1141 1142 // get the width/height of element after applying a fake font 1143 width = element.css('font-family', '__FAKEFONT__').width(); 1144 height = element.height(); 1145 1146 // set test font 1147 element.css('font-family', fontName); 1148 1149 return width !== element.width() || height !== element.height(); 1150 }, 1151 1152 createOrGet : function(selector, generate_func, context) { 1153 var $ret = $(selector, context); 1154 if ($ret[0]) { return $ret; } 1155 $ret = generate_func(context); 1156 if (!$ret.is(selector)) { 1157 console.error('$.createOrGet():generate_func is not "'+selector+'"'); 1158 } 1159 return $ret; 1160 }, 1161 1162 toBase : function(num, base){ 1163 var chars, type = typeof base, use_chars = false; 1164 if (type == 'number') { 1165 chars = '01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 1166 } else if (type == 'string') { 1167 chars = base; 1168 base = chars.length; 1169 use_chars = true; 1170 } else { 1171 throw new Error('invalid base (number or string):' + base); 1172 } 1173 if (base <= 36 && !use_chars) { 1174 return Number(num).toString(base); 1175 } 1176 var is_negative = num < 0; 1177 for (var str='', num = Math.abs(num); num > 0; num = Math.floor(num/base)) { 1178 str = chars[num % base] + str; 1179 } 1180 return (is_negative ? '-' : '') + str; 1181 }, 1182 1183 generateUUID4 : function(base){ 1184 // based on http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript 1185 // version 4 (base = 16) 1186 if (base < 2 || base > 62 ) { throw new Error('invalid base (2 to 62):' + base); } 1187 base = base || 16; 1188 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { 1189 var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8); 1190 return v.toString(16) 1191 }).split('-').map(function(v){ return $.toBase(parseInt(v, 16), base); }).join('-'); 1192 }, 1193 1194 }); 1195 1196 var _imgtest = $('<img>')[0]; 1197 _imgtest = 'naturalWidth' in _imgtest ? 0 : 'runtimeStyle' in _imgtest ? 1 : 2; 1198 1199 function dumpHTMLElement(v) { 1200 if (v === window) return 'Window'; 1201 if (v.nodeName) return v.nodeName + (v.id ? '#'+v.id : '') + (v.className ? ('.' + v.className.split(/\s+/).join('.')) : ''); 1202 return "" + v; 1203 }; 1204 1205 var _toString = $.fn.toString; 1206 $.fn.extend({ 1207 1208 events: function(callback, type){ 1209 /** 1210 * console.log $elm jquery events or callback(ev_def) 1211 */ 1212 return $(this).each(function(){ 1213 var root=this, elm=root; 1214 while (elm) { 1215 var evs = $._data(elm).events; 1216 if (!evs) { elm = elm.parentNode; continue; }
1217 Object.keys(evs).forEach(function(name){ 1218 if (type && type != name) { return; } 1219 evs[name].forEach(function(evd){ 1220 if (elm != root) { 1221 if (!evd.selector) { return; } 1222 if (!$(root).is(evd.selector, elm)) { return; } 1223 } 1224 (callback || console.info)(elm, evd); 1225 }) 1226 }); 1227 elm = elm.parentNode; 1228 } 1229 }); 1230 }, 1231 1232 csses: function(properties_array){ 1233 /** 1234 * $elm.cssDict(['prop1', 'prop2', ...]) 1235 * -> { 'prop1':'value', 'prop2':'value', ... } 1236 */ 1237 var $elm = this, ret = {}; 1238 properties_array.forEach(function(prop){ 1239 ret[prop] = $elm.css(prop); 1240 }); 1241 return ret; 1242 }, 1243 1244 assureUniqId: function(prefix, context){ 1245 /** 1246 * assure all elements ids are unique. 1247 * if target element has already have unique id in context, no effect. 1248 * if it doesn't have id or not unique, new unique (in the world) id is assigned. 1249 * 'unique' is based on RFC4122 version4 and base62 encoded. 1250 */ 1251 // assign prefix + generated uuid(62) as elements id when it is not have id or id is not unique in context. 1252 prefix = prefix || 'asuq-'; 1253 return $(this).each(function(){ 1254 var org_id = $(this).attr('id'); 1255 if (org_id) { 1256 if ($('[id]', context).filter(function(){ return this.id == org_id }).length > 1) { 1257 // duplicated id 1258 console.error('assureUniqId:duplicated id is found:' + org_id, this ); 1259 $(this).attr('data-duplicated-id', org_id); 1260 } else { 1261 // already have unique id in context 1262 return; 1263 } 1264 } 1265 $(this).attr('id', prefix + $.generateUUID4(62)); 1266 }); 1267 }, 1268 1269 reverse : [].reverse, 1270 1271 spaceless : function(){ 1272 /** 1273 * remove empty text nodes between child elements 1274 */ 1275 return $(this).each(function(){ 1276 $(this).contents().filter(function(){ 1277 if (this.nodeType == 3) { 1278 return /^\s*$/.test(this.textContent); 1279 } 1280 return false; 1281 }).remove(); 1282 }); 1283 }, 1284 1285 // http://jsfiddle.net/g30rg3/x8Na8/171/ 1286 // http://stackoverflow.com/questions/2360655/jquery-event-handlers-always-execute-in-order-they-were-bound-any-way-around-t 1287 bindFirst : function(name, fn) { 1288 this.on(name, fn); 1289 this.each(function(){ 1290 var handlers = $._data(this, 'events')[name.split('.')[0]]; 1291 var handler = handlers.pop(); 1292 handlers.splice(0, 0, handler); 1293 }); 1294 }, 1295 1296 toString : function(){ 1297 if (this[0]) { 1298 return '[object jQuery:' + this.selector +':[' + this.map(function(i, v){return dumpHTMLElement(v);}).toArray().join(',') + ']]'; 1299 } 1300 return _toString.call(this) + ''; 1301 }, 1302 1303 tagName : function() { 1304 return this.nodeName; 1305 }, 1306 1307 outerHTML : function(s) { 1308 if (s) { 1309 this.before(s); 1310 return s.append(this); 1311 } else { 1312 return $('<div>').append(this.clone()).html(); 1313 } 1314 }, 1315 1316 innerHTML : function(html) { 1317 if (arguments.length == 0) { 1318 return this.html(); 1319 } 1320 this[0].innerHTML = html; 1321 return this; 1322 }, 1323 1324 naturalSize : function () { 1325 /** 1326 * @return { width:<num>, height:<num>, src:"<src>" }, null : not img or no src or error, false : not loaded yet, 1327 */ 1328 var img = this[0]; 1329 if (img.nodeName !== "IMG") { 1330 return null; 1331 } 1332 //var src = this[0].attr('src'); 1333 if (!img.src) { 1334 return null; 1335 } 1336 if (img.complete === undefined || img.readyState == 'uninitialized') { 1337 return false; 1338 } 1339 var w, h; 1340 if (_imgtest == 0) { 1341 w = img.naturalWidth; 1342 h = img.naturalHeight; 1343 } else if (_imgtest == 1) { 1344 var img2 = new Image; 1345 img2.src = img.src; 1346 w = img2.width; 1347 h = img2.height; 1348 } else {
1349 var ow = img.width, oh = img.height; 1350 img.removeAttribute('width'); 1351 img.removeAttribute('height'); 1352 w = img.width; 1353 h = img.height; 1354 img.width = ow; 1355 img.height = oh; 1356 } 1357 if (img.complete == true && w === 0) { 1358 // img.complete and error on Chrome, Firefox, Safari 1359 return null; 1360 } 1361 return (w === 0 || w === undefined) ? false : { 1362 elm: this, 1363 src: this.attr('src'), 1364 width: w, 1365 height: h 1366 }; 1367 }, 1368 1369 imagesLoaded : function(func, timeout){ 1370 timeout = (timeout === undefined) ? 30 : timeout; 1371 var $images = $(this).find('img[src]').add( $(this).filter('img[src]') ).addClass('img_loading'); 1372 var _d = $.Deferred(function(_d){ 1373 var _ds = []; 1374 $images.each(function(){ 1375 var _d = $.Deferred(); 1376 _ds.push(_d); 1377 var $img = $(this); 1378 if ($img.naturalSize()) { 1379 $img.removeClass('img_loading'); 1380 _d.resolve($img.naturalSize()); 1381 } else { 1382 $img.one('load.imagesLoaded', function(){ 1383 $.poll(function(){ 1384 var size = $img.naturalSize(); 1385 return size === false; 1386 }, -1, 20).always(function(){ 1387 $img.removeClass('img_loading'); 1388 _d.resolve($img.naturalSize()); 1389 }); 1390 }).one('error.imagesLoaded', function(){ 1391 _d.resolve({ 1392 'error ' : arguments 1393 }); 1394 $img.removeClass('img_loading').addClass('img_load_error'); 1395 }); 1396 if ($img[0].complete || ($.browser.msie && $.browser.version < 9) ) { 1397 // for cached image 1398 $img.trigger('load'); 1399 } 1400 } 1401 }); 1402 $.when.apply(null, _ds).always(function(){ 1403 func && func.call(this, $images); 1404 _d.resolve(arguments); 1405 }); 1406 }); 1407 return func ? $images : _d; 1408 }, 1409 1410 redraw : function(func) { 1411 return this.hide(0, function(){$(this).show(); func && func($(this)); }); 1412 }, 1413 1414 overflowedX : function() { 1415 /* -5 for chrome bug (scrollHeight+1,2) */ 1416 var ret = ( this[0].clientWidth < this[0].scrollWidth ); 1417 return ret; 1418 }, 1419 overflowedY : function() { 1420 /* -5 for chrome bug (scrollWidth+1,2) */ 1421 var ret = (this[0].clientHeight < this[0].scrollHeight - 5); 1422 return ret; 1423 }, 1424 overflowed : function() { 1425 return $(this).overflowedY() || $(this).overflowedX(); 1426 }, 1427 1428 getFontSize : function() { 1429 if (document && document.defaultView && document.defaultView.getComputedStyle) { 1430 return parseInt(document.defaultView.getComputedStyle(this[0], null).fontSize); 1431 } 1432 var $tmp = $('#getFontSize')[0] ? $('#getFontSize') : $('<div id="getFontSize">').css({ 1433 'width':'1em', 1434 'height':'1em', 1435 'line-height':'1em', 1436 'padding':0, 1437 'position':'absolute' 1438 }).appendTo('body'); 1439 $tmp.appendTo(this).show(); 1440 var ret = $tmp[0].offsetWidth; 1441 $tmp.appendTo('body').hide(); 1442 return ret; 1443 }, 1444 1445 adjustFontSizeNoWrap : function(){ 1446 // adust font size without auto-wrap 1447 this.each(function(){ 1448 var $this = $(this).wrapInner('<div></div>'); 1449 var $wrapped = $this.children('div').css({ 1450 'white-space': 'nowrap', 1451 'padding' : 0, 1452 'margin' : 0, 1453 'width': 'auto', 1454 'font-size': 'inherit', 1455 'letter-spacing': 'inherit' 1456 }); 1457 var ratio = $wrapped[0].clientWidth / $wrapped[0].scrollWidth; 1458 var fs = Math.floor($this.getFontSize() * ratio); 1459 if (ratio < 1) { 1460 $this.css('font-size', fs + 'px' ); 1461 console.log('adjustFontSize():adjusted by ratio:' + $this + ':' + fs); 1462 } 1463 while (fs > 9 && $wrapped.css('white-space', 'normal').height() != $wrapped.css('white-space', 'wrapped').height()) { 1464 fs = Math.floor(fs * 0.9); 1465 $wrapped.css('font-size', fs + 'px'); 1466 } 1467 console.log('adjustFontSize():adjusted by resize:' + $this + ':' + fs); 1468 1469 $wrapped.contents().unwrap(); 1470 }); 1471 return this; 1472 }, 1473 1474 scrollIntoView : function(opts) { 1475 var o = this.offset(); 1476 if (!o) { return this; } 1477 opts = $.extend({ 1478 margin: 15 1479 }, opts); 1480 var margin = opts.margin; 1481 var container = window; 1482 var ct = $(container).scrollTop(), ch = container.clientHeight || $(container).height(), cb = ct + ch; 1483 var t = this.offset().top, h = this.outerHeight(), b = t + h; 1484 var nt = ct; 1485 if (t > cb) { 1486 nt = b - ch + margin; 1487 ct = nt; 1488 } 1489 if (b < ct) { 1490 nt = t - margin; 1491 } else if (t < ct) { 1492 nt = t - margin; 1493 } 1494 $(container).scrollTop(nt); 1495 return this; 1496 }, 1497 1498 scrollFixInView : function(do_scroll){ 1499 /** 1500 * save and restore position in view 1501 * usage: 1502 * $elm.scrollFixInView(); // save 1503 * : 1504 * $elm.scrollFixInView(true); // do scroll on saved 1505 */ 1506 var $this = $(this); 1507 if (!$this.is(':visible')) { return; } 1508 if (!do_scroll){ 1509 $this.data('_fixinview', $this[0].getBoundingClientRect()); 1510 } else { 1511 $(window).scrollTop($this.offset().top - $this.data('_fixinview').top); 1512 } 1513 return this; 1514 }, 1515 1516 /* ãã¾ãã¡ãchildãããã£ã¦ãç³»ã§ä½¿ããªã 1517 captureDocumentWrite : function(script) { 1518 var $this = $(this), state = { 1519 w : document.write, 1520 wl : document.writeln, 1521 buf : '' 1522 }; 1523 console.log('captureDocumentWrite:' + script); 1524 document.write = function(str){ 1525 state.buf += str; 1526 }; 1527 document.writeln = function(str){ 1528 sate.buf += str + '\n'; 1529 };
1530 var $div = $('<div id="captureDocumentWrite">').appendTo($('body')); 1531 if (script.match(/^(https?:)?\/\//)){ 1532 $('<div>').appendTo($div).replaceWith('<script src="' + script + '"></'+'script>'); 1533 $.doLater(function(){ 1534 console.log('captureDocumentWrite:captured:' + state.buf); 1535 $this.html(state.buf + $div.html()); 1536 document.write = state.w; 1537 document.writeln = state.wl; 1538 state = null; 1539 }, 100); 1540 } else if (script[0] == '<') { 1541 $('<div>').appendTo($div).replaceWith(script); 1542 $.doLater(function(){ 1543 console.log('captureDocumentWrite:captured:' + state.buf); 1544 $this.html(state.buf); 1545 document.write = state.w; 1546 document.writeln = state.wl; 1547 state = null; 1548 }, 100); 1549 } else { 1550 $('<div>').appendTo($this).replaceWith('<script>' + script + '</'+'script>'); 1551 $.doLater(function(){ 1552 console.log('captureDocumentWrite:captured:' + state.buf); 1553 $this.html(state.buf); 1554 document.write = state.w; 1555 document.writeln = state.wl; 1556 state = null; 1557 }, 100); 1558 } 1559 return this; 1560 } 1561 */ 1562 1563 sortByPosition: function(reverse){ 1564 var arr = this.toArray(); 1565 arr.sort(function(a, b){ 1566 if ( a === b) { return 0; } 1567 if ( !a.compareDocumentPosition ) { return a.sourceIndex - b.sourceIndex; } // for IE8- 1568 if ( a.compareDocumentPosition(b) & 2 ) { return 1; } 1569 return -1; 1570 }); 1571 if (reverse) { 1572 arr.reverse(); 1573 } 1574 return $(arr); 1575 }, 1576 1577 findSelf: function(selector){ 1578 return this.filter(selector).add(this.find(selector)); 1579 }, 1580 1581 closestSelf: function(selector){ 1582 if (this.is(selector)) { return this; } 1583 return this.closest(selector); 1584 }, 1585 1586 }); 1587 1588 var Mask = function(elem, opts) { 1589 this.opts = opts; 1590 this.$elem = $(elem); 1591 }; 1592 1593 // $.fn.cssHooks 1594 1595 function getMetrics($elem){
1596 var h = $elem.outerHeight(); 1597 var w = $elem.outerWidth(); 1598 var t = $elem.position().top; 1599 var l = $elem.position().left; 1600 var margin = $elem.css('margin'); 1601 var borderRadius = $elem.css('border-radius'); 1602 return { 1603 'border-radius' : borderRadius, 1604 position: $elem.css('position') == 'fixed' ? 'fixed' : 'absolute', 1605 margin: margin, 1606 top: t + 'px', 1607 left: l + 'px', 1608 height: h + 'px', 1609 width: w + 'px', 1610 zIndex: $elem.css('z-index') 1611 }; 1612 } 1613 1614 Mask.prototype = { 1615 constructor: Mask, 1616 toggle : function(){ 1617 return this[!!is_shown ? 'hide' : 'show'].apply(this, arguments); 1618 }, 1619 show : function(opts, proc){ 1620 var $elem = this.$elem.addClass('masked'); 1621 this.is_shown && this.$mask.hide(); 1622 opts = $.extend(this.opts, opts); 1623 var className = opts.className; 1624 className = className.call ? className(this.$elem) : className; 1625 var mask = this.$mask || this.$elem.next('.' + className); 1626 if (!mask[0]) { 1627 mask = $('<div>').addClass(className).appendTo(this.$elem.offsetParent()); 1628 } 1629 var css = getMetrics($elem); 1630 mask = mask.clone(); 1631 if (opts.html) { 1632 mask.append($(opts.html)); 1633 } 1634 mask.css($.extend(opts.css, { opacity:opts.opacity, background:opts.background }, css)) 1635 .appendTo(this.$elem.offsetParent()); 1636 1637 $elem.on('changemetrics.mask', function(){ 1638 mask.css($.extend(opts.css, { opacity:opts.opacity, background:opts.background }, css = getMetrics($(this)))); 1639 }); 1640 1641 proc && proc.call && proc.call(this, mask); 1642 this._org_style = $elem.attr('style'); 1643 this._org_position = $elem.css('position'); 1644 if (this._org_position == 'static') { 1645 $elem.css('position', 'relative'); 1646 } 1647 this._org_display = $elem.css('display'); 1648 if (this._org_display == 'inline') { 1649 $elem.css('display', 'inline-block'); 1650 } 1651 mask.show(); 1652 this.$mask = mask; 1653 this.is_shown = true; 1654 }, 1655 hide : function(opts, proc){ 1656 if (!this.is_shown){ 1657 return; 1658 } 1659 this.$elem.off('changemetrics.mask'); 1660 opts = $.extend(this.opts, opts); 1661 this.$elem.css('position', this._org_position); 1662 this.$elem.css('display', this._org_display); 1663 if (this._org_style) { 1664 this.$elem.attr('style', this._org_style); 1665 } else { 1666 this.$elem.removeAttr('style'); 1667 } 1668 this.$elem.removeClass('masked'); 1669 this.$mask.hide(); 1670 this.is_shown = false; 1671 }, 1672 destroy : function(){ 1673 this.$elem.off('changemetrics.mask'); 1674 this.hide(); 1675 this.$mask && this.$mask.remove(); 1676 this.$elem.removeData('mask').removeClass('masked'); 1677 } 1678 }; 1679 1680 $.fn.mask = function(opts, proc){ 1681 /** 1682 * mask and unmask 1683 * $(elem).mask(); 1684 * $(elem).mask({ 1685 * show: true, 1686 * className : 'customMask' or function(elem){} 1687 * }); 1688 * $(elem).mask('hide'); 1689 */ 1690 if (typeof opts == 'function') { 1691 proc = opts; 1692 opts = {}; 1693 } 1694 return this.each(function(){ 1695 var $this = $(this), data = $this.data('mask'), 1696 _opts = $.extend({}, $.fn.mask.defaults, $this.data(), typeof opts == 'object' && opts); 1697 if (!data) $this.data('mask', (data = new Mask(this, _opts))); 1698 if (typeof opts == 'string') data[opts](_opts, proc); 1699 else if (_opts.show) data.show(_opts, proc); 1700 }); 1701 }; 1702 1703 $.fn.mask.defaults = { 1704 show : true, 1705 className : 'mask', 1706 css : { 1707 'display' : 'block', 1708 'position' : 'absolute', 1709 '-webkit-box-sizing' : 'border-box', 1710 '-moz-box-sizing' : 'border-box', 1711 '-mz-box-sizing' : 'border-box', 1712 '-o-box-sizing' : 'border-box', 1713 'box-sizing' : 'border-box' 1714 }, 1715 html:'' 1716 }; 1717 1718 // workaround for safari bug 1719 // getComputedStyle().getPropretyValue is not support shorthand 1720 $.doLater(function(){ 1721 var s = $.setStyle('#cssstest { margin:10px; }
1721'), t = $('<div id="cssstest">').appendTo($('body')); 1722 if (t.css('margin') != t.css('margin-left')) { 1723 // alert('getComputedStylle is not support shorthand'); 1724 function mapSubProp(prop, repl, repls){ 1725 return $.closure([prop, repl], null, function(prop, sub, elem, computed, extra){ 1726 $elem = $(elem); 1727 return $.map(repls, function(v){ 1728 return $elem.css(prop.replace(repl, v)); 1729 }).join(' '); 1730 }); 1731 } 1732 function mapDirections(prop){ 1733 return mapSubProp(prop, 'Direction', ['Top', 'Right', 'Bottom', 'Left']); 1734 } 1735 $.each({ 1736 'margin': mapDirections('marginDirection'), 1737 'padding': mapDirections('paddingDirection'), 1738 'borderWidth': mapDirections('borderDirectionWidth'), 1739 'borderColor': mapDirections('borderDirectionColor'), 1740 'borderStyle': mapDirections('borderDirectionStyle'), 1741 'border' : mapSubProp('borderSub', 'Sub', ['Width', 'Color', 'Style']), 1742 'borderTop': mapDirections('borderTopDirection'), 1743 'borderRight': mapDirections('borderRightDirection'), 1744 'borderBottom': mapDirections('borderBottomDirection'), 1745 'borderLeft': mapDirections('borderLeftDirection'), 1746 'borderImage': mapSubProp('borderImageSub', 'Sub', ['Source', 'Slice', 'Width', 'Outset', 'Repeat']), 1747 'outline': mapSubProp('outlineSub', 'Sub', ['Color', 'Style', 'Width']), 1748 'borderRadius': mapSubProp('borderCornerRadius', 'Corner', ['TopLeft','TopRight','BottomRight','BottomLeft']), 1749 'font': mapSubProp('fontSub', 'Sub', ['Style', 'Veriant', 'Weight', 'Size', 'Family']), // XXX: size[/lineheight] 1750 'background': mapSubProp('backgroundSub', 'Sub', ['Color', 'Image', 'Repeat', 'Attachment', 'Position']), 1751 'listStyle': mapSubProp('listStyleSub', 'Sub', ['Type', 'Position', 'Image']), 1752 'transition': mapSubProp('transitionSub', 'Sub', ['Property', 'Duration', 'TimingFunction', 'Delay']) 1753 }, function(k, v){ 1754 $.cssHooks[k] = { 1755 get : v, 1756 set : $.closure([k], null, function(prop, elem, value) { 1757 elem.style[k] = value; 1758 }) 1759 }; 1760 }); 1761 } 1762 t.remove(); s.remove(); 1763 },10); 1764 if ($.browser.msie) { 1765 // XXX: outerWidth is very slow... 1766 } 1767 1768 if ($.browser.android) { 1769 // bug workaround type="date" on Android 4.0.4 Build/IMM76D 1770 $(document).on('focus', 'input[type="date"]', function(ev){ 1771 $(this).val($(this).val().replace(/^(\d+)-(\d)-(\d+)$/, '$1-0$2-$3').replace(/^(\d+)-(\d+)-(\d)$/, '$1-$2-0$3')); 1772 }); 1773 } 1774 1775 // events 1776 1777 // see http://stackoverflow.com/questions/1449666/create-a-jquery-special-event-for-content-changed 1778 $.fn.watch = function(id, opts) { 1779 /** 1780 * Watch some value and trigger 'change', 'start' and 'end' function. 1781 * $(elem).watch('some id', { 1782 * interval: 100, 1783 * watch: function(){ 1784 * return $(this).some.watching.value; 1785 * }, 1786 * onchange: function(id, mode, old, cur) { 1787 * if (mode == 'start') {...} 1788 * else if (mode == 'change') {...} 1789 * else if (mode == 'end') {...} 1790 * } 1791 * }); 1792 */ 1793 opts = $.extend({ 1794 interval: 1000/30, 1795 watch: function(){}, 1796 onchange: function(id, mode, old, cur){} 1797 }, opts); 1798 return this.each(function(){ 1799 var _self = this; 1800 var o = opts.watch.call(_self), n, m = 0, s = 0; 1801 $(_self).data('watch_t', setInterval(function(){ 1802 if ((n = opts.watch.call(_self)) !== o) { 1803 if (m == 0) { 1804 m = 1; 1805 s = n; 1806 opts.onchange.call(_self, id, 'start', o, n); 1807 } else { 1808 opts.onchange.call(_self, id, 'change', o, n, s); 1809 } 1810 o = n; 1811 } else { 1812 if (m == 1) { 1813 m = 0; 1814 opts.onchange.call(_self, id, 'end', s, n); 1815 } 1816 } 1817 }, opts.interval)); 1818 }); 1819 }; 1820 1821 $.fn.unwatch = function(id){ 1822 return this.each(function(){ 1823 clearInterval($(this).data('watch_t')); 1824 }); 1825 }; 1826 1827 function watchScrollTop(){ return $(this).scrollTop(); } 1828 function watchSize(){ var t = $(this); return t.width() + ',' + t.height(); } 1829 function watchOverflow() { 1830 return $(this).innerHeight() < $(this)[0].scrollHeight; 1831 } 1832 function watchMetrics(){ 1833 return $.toJSON(getMetrics($(this))); 1834 } 1835 1836 $.each([ 1837 ['scrolling', 'scrolling', watchScrollTop, 'change'], 1838 ['scrollstart', 'scrolling', watchScrollTop, 'start'], 1839 ['scrolled', 'scrolling', watchScrollTop, 'end'], 1840 ['resizing', 'resizing', watchSize, 'change'], 1841 ['resizestart', 'resizing', watchSize, 'start'], 1842 ['resized', 'resizing', watchSize, 'end'], 1843 ['overflow', 'overflow', watchOverflow, 'start'], 1844 ['changemetrics', 'changemetrics', watchMetrics, 'start'] 1845 ], function(i, v){ 1846 1847 var eventType = v[0], watchId = v[1], watchFunc = v[2], watchType = v[3]; 1848 $.event.special[eventType] = { 1849 setup: function(data, namespace, eventHandle){ 1850 $(this).watch(watchId + '.' + watchType, { 1851 watch: watchFunc, 1852 onchange: function(id, type, old, cur, start){ 1853 if (type == watchType) { 1854 var ev = $.Event(eventType); 1855 ev[eventType] = { start: start, old:old, cur: cur }; 1856 $.event.dispatch.call(this, ev); 1857 } 1858 } 1859 }); 1860 }, 1861 teardown: function(){ 1862 $(this).unwatch(watchId); 1863 } 1864 }; 1865 1866 $.fn[eventType] = function(fn){
1867 return this.on(eventType, fn); 1868 }; 1869 1870 }); 1871 1872 // fire resized on window when resize end 1873 console.log('set resized event on window'); 1874 (function(w){ 1875 var t = null; 1876 $(w).off('resized').on('resize', function(ev){ 1877 clearTimeout(t); 1878 t = setTimeout(function(){ 1879 $(window).trigger('resized', [ev]); 1880 t = null; 1881 }, 1000/30); 1882 }); 1883 })(window); 1884 1885 /* éããªã : jquery-mobile-touch.js ã«ç§»ç®¡ 1886 var touch = null, has_android_touch_bug = ($.browser.android && $.browser.android.version >= "3.0.0" && $.browser.android.version < "4.1.0"); 1887 1888 function calcTouchDelta(){ 1889 var radian = Math.atan2(touch.delta.y, touch.delta.x); 1890 var angle = Math.round(radian * 180 / Math.PI); 1891 if (angle < 0) { 1892 angle = 360 - Math.abs(angle); 1893 } 1894 touch.angle = angle; 1895 if (angle <= 45 || angle >= 315) { 1896 touch.direction = 'right'; 1897 } else if (angle > 45 && angle < 135) { 1898 touch.direction = 'down'; 1899 } else if (angle >= 135 && angle <= 225) { 1900 touch.direction = 'left'; 1901 } else { 1902 touch.direction = 'up'; 1903 } 1904 touch.distance = Math.round(Math.sqrt(Math.pow(touch.delta.x, 2)+Math.pow(touch.delta.y, 2))); 1905 } 1906 1907 $(document).on('touchstart', function(ev){ 1908 var oev = ev.originalEvent, ot = oev.touches ? oev.touches[0] : oev; 1909 touch = { 1910 start: { 1911 x: ot.clientX, y: ot.clientY, 1912 px: ot.pageX, py: ot.pageY 1913 }, 1914 page_start: { x: ot.pageX, y: ot.pageY }, 1915 target : ot.target 1916 }; 1917 }).on('touchmove', function(ev){ 1918 if (!touch) { return; } 1919 var oev = ev.originalEvent, ot = oev.touches ? oev.touches[0] : oev; 1920 touch.delta = { 1921 x: ot.clientX - touch.start.x, 1922 y: ot.clientY - touch.start.y, 1923 px: ot.pageX - touch.page_start.x, 1924 py: ot.pageY - touch.page_start.y, 1925 target: ot.target 1926 }; 1927 // calcTouchDelta(); 1928 if (has_android_touch_bug && Math.abs(touch.delta.y) < 5) { 1929 ev.preventDefault(); 1930 $(touch.target).trigger($.Event('swiping', { origialEvent:ev, swipe:touch })); 1931 } 1932 }).on('touchend', function(ev){ 1933 if (!touch || !touch.delta) { return; } 1934 // var oev = ev.originalEvent, ot = oev.touches ? oev.touches[0] : oev; 1935 touch.end = { 1936 x: touch.start.x + touch.delta.x, 1937 y: touch.start.y + touch.delta.y, 1938 px: touch.start.px + touch.delta.px, 1939 py: touch.start.py + touch.delta.py 1940 }; 1941 calcTouchDelta(); 1942 if (touch.distance > 30) { 1943 $(touch.target) 1944 .trigger($.Event('swipe', { originalEvent:ev, swipe:touch })) 1945 .trigger($.Event('swipe' + touch.direction, { originalEvent:ev, swipe: touch })); 1946 if (ev.type == 'mouseup') { 1947 ev.preventDefault(); 1948 } 1949 } 1950 touch = null; 1951 }); 1952 */ 1953 1954 1955 /******************************** 1956 * autogrow number of rows at textrea 1957 * usage: 1958 * $jqueryobj.autogrow(opts); 1959 * $.autogrow(selector, opts); 1960 * opts: 1961 * "destroy" 1962 * { 1963 * autoShrink: <bool:false> 1964 * minRows: <num:4> 1965 * // growRows: <num:4> : obsolete 1966 * maxRows: <num:40> 1967 * } 1968 * event: 1969 * autogrowed: fire when textarea's row is changed 1970 */ 1971 (function (){ 1972 1973 var DEBUG = false; 1974 1975 var AUTOGROW_EVENTS = 'focus.autogrow keyup.autogrow paste.autogrow change.autogrow'; 1976 1977 // https://github.com/Codecademy/textarea-helper/blob/master/textarea-helper.js 1978 var mirrorStyles = [ 1979 // appearances, 1980 '-webkit-appearance', '-moz-appearance', '-ms-appearance', 'appearance', 1981 // Box Styles. 1982 'box-sizing', 'height', 'width', 'padding-bottom', 'padding-left', 'padding-right', 'padding-top' 1983 // Font stuff. 1984 , 'font-family', 'font-size', 'font-style', 'font-variant', 'font-weight' 1985 // Spacing etc. 1986 , 'word-spacing', 'letter-spacing', 'line-height', 'text-decoration', 'text-indent', 'text-transform' 1987 // Breaks 1988 ,'word-break', 'word-wrap', 'overflow-wrap', 'white-space' 1989 // The direction. 1990 , 'direction' ]; 1991 1992 function getMirror($ta) { 1993 1994 var $mirror = $('#autogrow-ta-mirror-div') 1995 if (!$mirror[0]) { 1996 $mirror = $('<div></div>') 1997 .attr('id', 'autogrow-ta-mirror-div') 1998 .css({ 1999 // border:"1px solid red", // debug */ 2000 visibility:'hidden', 2001 opacity:0, 2002 position:'absolute', 2003 top:'-9999px', 2004 left:'-9999px', 2005 zIndex:-1 2006 }).appendTo('body'); 2007 } 2008 2009 // Copy styles. 2010 var styles = {}; 2011 for ( var i = 0, style; style = mirrorStyles[i]; i++) { 2012 styles[style] = $ta.css(style); 2013 } 2014 $mirror.css(styles).css({ 2015 'height':'auto', 2016 'overflow-y':$ta[0].clientWidth < $ta[0].scrollWidth ? 'scroll' : 'visible', 2017 'overflow-x':'hidden' 2018 }); 2019 // http://blog.jquery.com/2012/08/16/jquery-1-8-box-sizing-width-csswidth-and-outerwidth/ 2020 if ($mirror.outerWidth() != $ta.outerWidth()) { 2021 // seems that box-sizing = border-box 2022 $mirror.css('width', $ta.outerWidth() + 'px' ); 2023 } 2024 if ($.browser.ios) { 2025 $mirror.css('padding-left', parseFloat($ta.css('padding-left'),10) + 3 + 'px' ); 2026 $mirror.css('padding-right', parseFloat($ta.css('padding-right'),10) + 3 + 'px' ); 2027 } 2028 2029 return $mirror; 2030 } 2031 2032 var t = null; 2033 function ta_autogrow($ta) { 2034 clearTimeout(t); 2035 t = setTimeout(function() { 2036 _ta_autogrow($ta); 2037 t = null; 2038 }, 100); 2039 } 2040 2041 function _ta_autogrow($ta) { 2042 if (!$ta.is(':visible')) { return; } 2043 2044 // console.log('_ta_autogrow()', $ta); 2045 var text = $ta.val(); 2046 var old_text = $ta.data('old_text'); 2047 if (text == old_text) { return; } 2048 2049 var opts = $ta.data('autogrow') || {}; 2050 2051 var $mirror = getMirror($ta); 2052 var _hfunc = $ta.css('box-sizing') == 'border-box' ? 'outerHeight' : 'height';
2053 2054 $mirror.css({ 2055 minHeight:0, 2056 maxheight:'none' 2057 }); 2058 var minHeight = $mirror.html(new Array(opts.minRows).join('A<br>'))[_hfunc](); 2059 var maxHeight = $mirror.html(new Array(opts.maxRows).join('A<br>'))[_hfunc](); 2060 2061 $ta.css({ 2062 minHeight:+'px', 2063 maxHeight:+'px' 2064 }); 2065 2066 $mirror.html( 2067 text.replace(/&/g,'&') 2068 .replace(/</g,'<') 2069 .replace(/(\r\n|\r|\n)/g, '<br>') 2070 .replace(/<br>$/, '<br> ') 2071 .replace(/^$/, ' ') 2072 ); 2073 2074 if (DEBUG) { 2075 $ta.css({ 2076 background:'#ccf', 2077 borderRadius:0 2078 }); 2079 $mirror.css({ 2080 visibility:'visible', 2081 opacity:'1', 2082 zIndex:'1000', 2083 background:'#fcc', 2084 top:($ta.offset().top + $ta.outerHeight()) + 'px', 2085 left:($ta.offset().left) + 'px', 2086 }); 2087 } 2088 2089 var new_height = $mirror[_hfunc](); 2090 var old_height = $ta[_hfunc](); 2091 2092 var vScrollbarHeight = 0; 2093 if ($ta.css('overflow-x') == 'scroll' || ($ta.css('overflow-x') == 'auto' && $ta.overflowedX())) { 2094 vScrollbarHeight = $.getScrollbarHeight(); 2095 } 2096 2097 if (opts.autoShrink) { 2098 } else { 2099 if (new_height + vScrollbarHeight < old_height) { 2100 return; 2101 } 2102 } 2103 2104 $ta.height(new_height + vScrollbarHeight); 2105 2106 if (new_height != old_height) { 2107 $ta.height(new_height + vScrollbarHeight); 2108 if ($.browser.iphone){ 2109 // iPhoneã®ã¿ãªãã2è¡ã®ã¨ãã«ã«ã¼ã½ã«çãåããªãã£ãããã 2110 if ($ta.height() <= maxHeight) { 2111 $ta.scrollTop(0).trigger('focus'); 2112 } 2113 } 2114 $ta.trigger('autogrowed'); 2115 } 2116 } 2117 2118 $.extend({ 2119 autogrow : function(selector, opts) { 2120 $(document) 2121 .off('focus.autogrow change.autogrow', selector) 2122 .on('focus.autogrow change.autogrow', selector, function(ev) { 2123 var $this = $(this); 2124 if ($this.data('autogrow')) { 2125 return; 2126 } 2127 return $this.autogrow(opts); 2128 }); 2129 } 2130 }); 2131 2132 // IEãããããã 2133 // å½±é¿ã大ããã®ã§ããã©ã«ãã§å ¥ããã®ã¯ããã¦ããã 2134 // 使ãã¨ã㯠textarea ã® font-familyãfont-sizeãCSSã§è¨å®ãããã¨(ããã©ã«ãã«ä»»ããªã)ã 2135 // $.setStyle('textarea,input,select{font-size:inherit;font-family:inherit;}').prependTo('head'); 2136 2137 $.fn.extend({ 2138 autogrow : function(opts) { 2139 /** 2140 * auto grow height of textareas as no scrollbar. 2141 */ 2142 2143 2144 if (opts == 'destroy') { 2145 this.removeData('autogrow'); 2146 return; 2147 } 2148 2149 opts = $.extend({ 2150 autoShrink : false, 2151 minRows : 4, 2152 // growRows : 4, 2153 maxRows : 40 2154 }, opts); 2155 if (opts.minRows < 1) { opts.minRows = 1; } 2156 // if (opts.growRows < 1){ opts.growRows = 1; } 2157 if (opts.maxRows < 1) { opts.maxRows = 1; } 2158 2159 var t = null; 2160 2161 return this.each(function() { 2162 var $ta = $(this); 2163 if (!$ta.is('textarea')) { 2164 return; 2165 } 2166 var pos = $ta.css('position'); 2167 var disp = $ta.css('display'); 2168 $ta.css({ 2169 'word-break' : 'break-all', 2170 'overflow-y' : 'hidden', 2171 'height' : 'auto', 2172 'display' : disp == 'inline' ? 'inline-block' : disp, 2173 'position' : pos == 'static' ? 'relative' : pos 2174 }); 2175 $ta.off(AUTOGROW_EVENTS) 2176 .on(AUTOGROW_EVENTS, function(ev) { 2177 // console.log(ev); 2178 var $ta = $(this), opts = $ta.data('autogrow'); 2179 ta_autogrow($ta); 2180 }); 2181 $ta.data('autogrow', opts); 2182 ta_autogrow($ta); 2183 }); 2184 } 2185 2186 }); 2187 })(); 2188 2189 (function($){ 2190 /* é åã¯ãªã¢ãã¿ã³ */ 2191 /** 2192 * $.inputclear(selector, opts) 2193 * $elm.inputclear(opts) 2194 * opts: { 2195 * clear_image_url:'<url for clear button image - recommend svg>' 2196 * } 2197 */ 2198 2199 /* http://stackoverflow.com/questions/6258521/clear-icon-inside-input-text */ 2200 /* svg data url generated 2201 * from: http://marketblog.envato.com/resources/25-icon-sets-svg-format/ 2202 * change color by inkscape 2203 * base64 by b64.io 2204 */ 2205 2206 var DEFAULTS = { 2207 clear_image_url:'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIgICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgICB4bWxuczpzb2RpcG9kaT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQiICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiICAgd2lkdGg9IjgiICAgaGVpZ2h0PSI4IiAgIHZpZXdCb3g9IjAgMCA4IDgiICAgaWQ9InN2ZzIiICAgdmVyc2lvbj0iMS4xIiAgIGlua3NjYXBlOnZlcnNpb249IjAuNDguNSByMTAwNDAiICAgc29kaXBvZGk6ZG9jbmFtZT0ieF90cmFuczUwLnN2ZyI+ICA8bWV0YWRhdGEgICAgIGlkPSJtZXRhZGF0YTEwIj4gICAgPHJkZjpSREY+ICAgICAgPGNjOldvcmsgICAgICAgICByZGY6YWJvdXQ9IiI+ICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD4gICAgICAgIDxkYzp0eXBlICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPiAgICAgICAgPGRjOnRpdGxlPjwvZGM6dGl0bGU+ICAgICAgPC9jYzpXb3JrPiAgICA8L3JkZjpSREY+ICA8L21ldGFkYXRhPiAgPGRlZnMgICAgIGlkPSJkZWZzOCIgLz4gIDxzb2RpcG9kaTpuYW1lZHZpZXcgICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIgICAgIGJvcmRlcmNvbG9yPSIjNjY2NjY2IiAgICAgYm9yZGVyb3BhY2l0eT0iMSIgICAgIG9iamVjdHRvbGVyYW5jZT0iMTAiICAgICBncmlkdG9sZXJhbmNlPSIxMCIgICAgIGd1aWRldG9sZXJhbmNlPSIxMCIgICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwIiAgICAgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIgICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTExOCIgICAgIGlua3NjYXBlOndpbmRvdy1oZWlnaHQ9IjY4NSIgICAgIGlkPSJuYW1lZHZpZXc2IiAgICAgc2hvd2dyaWQ9ImZhbHNlIiAgICAgaW5rc2NhcGU6em9vbT0iMjkuNSIgICAgIGlua3NjYXBlOmN4PSI0IiAgICAgaW5rc2NhcGU6Y3k9IjQiICAgICBpbmtzY2FwZTp3aW5kb3cteD0iNzMwIiAgICAgaW5rc2NhcGU6d2luZG93LXk9IjM0OSIgICAgIGlua3NjYXBlOndpbmRvdy1tYXhpbWl6ZWQ9IjAiICAgICBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJzdmcyIiAvPiAgPHBhdGggICAgIGQ9Ik0xLjQxIDBsLTEuNDEgMS40MS43Mi43MiAxLjc4IDEuODEtMS43OCAxLjc4LS43Mi42OSAxLjQxIDEuNDQuNzItLjcyIDEuODEtMS44MSAxLjc4IDEuODEuNjkuNzIgMS40NC0xLjQ0LS43Mi0uNjktMS44MS0xLjc4IDEuODEtMS44MS43Mi0uNzItMS40NC0xLjQxLS42OS43Mi0xLjc4IDEuNzgtMS44MS0xLjc4LS43Mi0uNzJ6IiAgICAgaWQ9InBhdGg0IiAgICAgc3R5bGU9ImZpbGw6IzgwODA4MDtmaWxsLW9wYWNpdHk6MSIgLz48L3N2Zz4=' 2208 }; 2209 2210 function setInputClearStyle(clear_image_url){
2211 // console.log('setInputClearStyle():' + clear_image_url); 2212 var style = [ 2213 '.inputclear_shown {', 2214 'background-repeat:no-repeat;', 2215 'background-size:1em auto;', 2216 'background-position:right .1em top .2em;', 2217 'padding-right:1.4em!important;', 2218 2219 'background-image:url(__IMG_URL__);', 2220 '}', 2221 '.inputclear_shown::-ms-clear { display:none; }', 2222 '.oninputclear { cursor:pointer; }' 2223 ].join('') 2224 .replace('__IMG_URL__', clear_image_url||DEFAULTS.clear_image_url); 2225 $.setStyle(style, 'style-input-clear'); 2226 } 2227 2228 setInputClearStyle(); 2229 2230 function setInputClearToggle($input){ 2231 // console.log('setInputClearToggle()', $input[0]); 2232 var shown = !!$input.val(); 2233 $input.toggleClass('inputclear_shown', shown); 2234 var image_url = ($input.data('inputclear_opts')||{}).clear_image_url; 2235 if (image_url) { 2236 $input.css('background-image', shown?'url('+image_url+')':'none'); 2237 } 2238 } 2239 2240 function setInputClearOffsets($input){ 2241 // console.log('setInputClearOffsets()', $input[0]); 2242 var offset = $input.offset(), w = $input.outerWidth(), h = $input.outerHeight(); 2243 var ret = { 2244 'top':offset.top, 2245 'left':offset.left, 2246 'width':w, 2247 'height':h, 2248 'fs':parseFloat($input.css('font-size')) /* fontsize in pixel */ 2249 } 2250 $input.data('offsets', ret); 2251 return ret; 2252 } 2253 2254 function setInputClearCursor($input, ev){ 2255 // console.log('setInputClearCursor()', $input[0]); 2256 var offsets = $input.data('offsets')||setInputClearOffsets($input); 2257 var oninputclear = 2258 ev.clientX > offsets.left + offsets.width - 1.3 * offsets.fs 2259 && ev.clientY < offsets.top + 1.3 * offsets.fs; 2260 $input.toggleClass('oninputclear', oninputclear); 2261 } 2262 2263 function doInputClear($input, ev) { 2264 if ($input.is('.oninputclear')) { 2265 // console.log('doInputClear()'); 2266 ev.preventDefault(); 2267 $input.removeClass('oninputclear').val('').trigger('change'); 2268 } 2269 } 2270 2271 function setEventsAll(target_selector) { 2272 $(document) 2273 .off('input.ic focus.ic change.ic', target_selector) 2274 .on('input.ic focus.ic change.ic', target_selector, function(ev){ 2275 setInputClearToggle($(this)); 2276 }) 2277 .off('mouseenter.ic', target_selector) 2278 .on('mouseenter.ic', target_selector, function(ev){ 2279 setInputClearOffsets($(this)); 2280 }) 2281 .off('mouseenter.ic', target_selector) 2282 .on('mousemove.ic', target_selector, function(ev){ 2283 setInputClearCursor($(this), ev); 2284 }) 2285 .off('touchstart.ic click.ic', target_selector) 2286 .on('touchstart.ic click.ic', target_selector, function(ev){ 2287 doInputClear($(this), ev); 2288 }); 2289 } 2290 2291 function setEventsToElm($elm) { 2292 $elm 2293 .off('input.ic focus.ic change.ic') 2294 .on('input.ic focus.ic change.ic', function(ev){ 2295 setInputClearToggle($(this)); 2296 }) 2297 .off('mouseenter.ic') 2298 .on('mouseenter.ic', function(ev){ 2299 setInputClearOffsets($(this)); 2300 }) 2301 .off('mouseenter.ic') 2302 .on('mousemove.ic', function(ev){ 2303 setInputClearCursor($(this), ev); 2304 }) 2305 .off('touchstart.ic click.ic') 2306 .on('touchstart.ic click.ic', function(ev){ 2307 doInputClear($(this), ev); 2308 }); 2309 } 2310 2311 var opts = {}; 2312 $.extend({ 2313 'inputclear':function(selector, opts){ 2314 selector = selector === undefined ? 'input.clearable' : selector; 2315 var opts = $.extend({}, DEFAULTS, opts); 2316 setInputClearStyle(opts.clear_image_url); 2317 setEventsAll(selector); 2318 } 2319 }); 2320 $.fn.extend({ 2321 'inputclear':function(opts){ 2322 return this.each(function(){ 2323 var $input = $(this); 2324 var opts = $.extend({}, DEFAULTS, opts); 2325 $input.data('inputclear_ots', opts); 2326 setEventsToElm($input); 2327 }); 2328 } 2329 }); 2330 2331 })($); 2332 2333 // for-select toggle 2334 // <select name="xxx">..</select> 2335 // <div data-for-select="xxx" data-for-selected="val1">...</div> 2336 // <div data-for-select="xxx" data-for-selected="val2">...</div> 2337 // <div data-for-select="xxx" data-for-selected="val3">...</div> 2338 $(function(){ 2339 function toggleForSelected($select){ 2340 $select.each(function(){ 2341 var $select = $(this), name=$select.attr('name'), selected = $select.val(); 2342 $select.closest('form').find('[data-for-select][data-for-selected]').each(function(){ 2343 var $t = $(this); 2344 if ($t.attr('data-for-select') == name){ 2345 var hide = $t.attr('data-for-selected') != selected; 2346 $t.css('display', hide ? 'none' : ''); 2347 } 2348 }); 2349 }); 2350 } 2351 $(document).on('change.forselect', 'select[name]', function(ev){ 2352 toggleForSelected($(this)); 2353 }); 2354 toggleForSelected($('select[name]')); 2355 }) 2356 2357 // Deferred Queue 2358 // http://samarskyy.blogspot.jp/2011/10/jquery-deferred-queues.html 2359 function DeferredQueue(){ 2360 this.promise = $(this).promise(); 2361 } 2362 DeferredQueue.prototype.add = function(func, arg){ 2363 /** 2364 * var q = $.DeferredQueue(); 2365 * q.add(function(arg){ this.resolve() or this.reject() }, arg1, arg2, ...) 2366 * q.add(function(arg){ this.resolve() or this.reject() }, arg1, arg2, ...) 2367 */ 2368 var _this = this; 2369 var args = Array.prototype.slice.call(arguments, 1); 2370 return this.promise = this.promise.then(function(){ 2371 return $.Deferred(function(){
2372 try { 2373 return func.apply(this, args); 2374 } catch (ex) { 2375 this.reject(ex); 2376 return _this.promise = $(_this).promise(); 2377 } 2378 }).promise(); 2379 }) 2380 }; 2381 DeferredQueue.prototype.wait = function(wait_ms){ 2382 this.add(function(){ 2383 var _this = this; 2384 setTimeout(function(){ 2385 _this.resolve(); 2386 }, wait_ms); 2387 }); 2388 }; 2389 $.DeferredQueue = DeferredQueue; 2390 2391 // LocalDate : for input[type="datetime-local"] 2392 $.toLocalDate = function(date){ 2393 date = (date instanceof Date) ? date : new Date(date); 2394 return (new Date(date.getTime() - date.getTimezoneOffset() * 60000)) 2395 .toISOString() 2396 .replace(/(Z|[+-]\d{2}(:?\d{2})?)$/, ''); 2397 } 2398 $.fromLocalDate = function(localdate){ 2399 var offset = new Date().getTimezoneOffset() * 60000; 2400 return new Date(new Date(localdate + 'Z').getTime() + offset); 2401 } 2402 2403 function ajax_cached(opts, force_clear){ 2404 // console.log('ajax_cached:\t' + opts.url); 2405 2406 var cache_key = opts.url + ':' + JSON.stringify(opts.data || {}), 2407 cached = ajax_cached._cache[cache_key]; 2408 if (!opts.cache || !cached || cached.state == 'error'){ 2409 console.log('ajax_cached:regist\t' + cache_key); 2410 var _d = $.ajax(opts); 2411 _d.then(function(res){ 2412 console.log('ajax_cached:success\t' + cache_key); 2413 ajax_cached._cache[cache_key] = { 2414 state: 'success', 2415 args: Array.from(arguments), 2416 }; 2417 }).fail(function(){ 2418 console.log('ajax_cached:error\t' + cache_key); 2419 ajax_cached._cache[cache_key] = { 2420 state: 'error', 2421 args: Array.from(arguments), 2422 }; 2423 }).always(function(){ 2424 ajax_cached._cache[cache_key]._expire_t = 2425 setTimeout(function(cache_key){ 2426 console.log('ajax_cached:expire\t' + cache_key); 2427 delete ajax_cached._cache[cache_key]; 2428 }.bind(null, cache_key), ajax_cached._expire_ms); 2429 }); 2430 var cache = { 2431 state: 'loading', 2432 _d: _d, 2433 }; 2434 ajax_cached._cache[cache_key] = cache; 2435 return cache._d; 2436 } else if (cached.state == 'loading') { 2437 console.log('ajax_cached:wait\t' + cache_key); 2438 return cached._d; 2439 } else { 2440 console.log('ajax_cached:cached\t' + cache_key); 2441 var _d = $.Deferred(); 2442 if (cached.state == 'success') { 2443 _d.resolve.apply(_d, cached.args); 2444 } else { 2445 _d.reject.apply(_d, cached.args); 2446 } 2447 return _d.promise(); 2448 } 2449 } 2450 2451 ajax_cached._cache = {}; 2452 ajax_cached._expire_ms = 10 * 60 * 1000; 2453 2454 $.extend({ 2455 ajax_cached: ajax_cached, 2456 }); 2457})(jQuery); 2458(function ($) { 2459 // ã¤ãã³ãã®å®è¡ç¶æ ãä¿æãããããï¼è¦ç´ ãã¨ã«è¨æ¶ï¼ 2460 const loadedFlag = new WeakMap(); 2461 2462 /** 2463 * jQuery special event: 'windowonload' 2464 * 2465 * ç®çï¼ 2466 * - $(window).on('load') ã®ä»£æ¿ã¨ãã¦ãjQuery 3 ç§»è¡å¾ã§ãè¦åãªãã§ä½¿ãã 2467 * - ãã¼ã¸ãæ¢ã« load æ¸ã¿ã§ãã£ã¦ã確å®ã«ãã³ãã©ã1åã ãå¼ã°ãã 2468 * - $(function () { $(window).on('windowonload', fn); }) ã®ãããªé åºã§ã fn ãå¿ ãå¾ããå®è¡ããã 2469 * - load æ¸ã¿å¤å®å¾ã®å³æå®è¡ã¯ setTimeout(..., 0) ã§ defer ãããé åºä¿è¨¼ããã 2470 * 2471 * ä½¿ç¨æ¹æ³ï¼ 2472 * $(window).on('windowonload', function (e) { ... }); 2473 * $(window).one('windowonload', function (e) { ... }); // æ¨å¥¨ï¼1åã ãå®è¡ããã 2474 * 2475 * ç§»è¡ãã¿ã¼ã³ï¼ 2476 * $(window).on('load', fn); // 徿¥ã³ã¼ãï¼è¦åããï¼ 2477 * $(window).on('load windowonload', fn); // ç§»è¡æï¼è¦ååºããå®å ¨ï¼ 2478 * $(window).on('windowonload', fn); // æçµå½¢ï¼è¦åãªããé åºä¿è¨¼ããï¼ 2479 */ 2480 $.event.special.windowonload = { 2481 setup() { 2482 const el = this; 2483 2484 // ãã®ã¤ãã³ã㯠window å°ç¨ããã以å¤ã§ã¯ä½ãããªã 2485 if (el !== window) return false; 2486 2487 // ãã§ã«ç»é²æ¸ã¿ã§ããã°ä½ãããªã 2488 if (loadedFlag.get(el)) return false; 2489 2490 // å®è¡å¦çï¼ä¸åº¦ã ããsetTimeout ã§ defer ãã¦å®è¡ 2491 const runOnce = () => { 2492 if (!loadedFlag.get(el)) { 2493 loadedFlag.set(el, true); 2494 // defer ã«ãã $(fn) ããå¾ã«ç¢ºå®ã«çºç«ãã 2495 setTimeout(() => { 2496 $(el).triggerHandler('windowonload'); 2497 }, 0); 2498 } 2499 }; 2500 2501 // ãã§ã«ãã¼ã¸ã load æ¸ã¿ãªã峿å®è¡ 2502 if (document.readyState === 'complete') { 2503 runOnce(); 2504 return false; // ã¤ãã³ãç»é²ã¯ä¸è¦ 2505 } 2506
2507 // ã¾ã load æ¸ã¿ã§ãªããã°ããã¤ãã£ã load ãä¸åº¦ã ãç£è¦ 2508 $(el).one('load', runOnce); 2509 return true; 2510 }, 2511 2512 teardown() { 2513 // ã¯ãªã¼ã³ã¢ããå¦çï¼load ã¤ãã³ããè§£é¤ï¼ 2514 $(this).off('load'); 2515 } 2516 }; 2517})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.