[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 YUI.add('yui2-get', function(Y) { 2 var YAHOO = Y.YUI2; 3 /* 4 Copyright (c) 2011, Yahoo! Inc. All rights reserved. 5 Code licensed under the BSD License: 6 http://developer.yahoo.com/yui/license.html 7 version: 2.9.0 8 */ 9 /** 10 * Provides a mechanism to fetch remote resources and 11 * insert them into a document 12 * This utility can fetch JavaScript and CSS files, inserting script 13 * tags for script and link tags for CSS. Note, this 14 * is done via the normal browser mechanisms for inserting 15 * these resources and making the content available to 16 * code that would access it. Be careful when retreiving 17 * remote resources. Only use this utility to fetch 18 * files from sites you trust. 19 * 20 * @module get 21 * @requires yahoo 22 */ 23 24 /** 25 * Fetches and inserts one or more script or link nodes into the document. 26 * This utility can fetch JavaScript and CSS files, inserting script 27 * tags for script and link tags for CSS. Note, this 28 * is done via the normal browser mechanisms for inserting 29 * these resources and making the content available to 30 * code that would access it. Be careful when retreiving 31 * remote resources. Only use this utility to fetch 32 * files from sites you trust. 33 * 34 * @namespace YAHOO.util 35 * @class YAHOO.util.Get 36 */ 37 YAHOO.util.Get = function() { 38 39 /** 40 * hash of queues to manage multiple requests 41 * @property queues 42 * @private 43 */ 44 var queues={}, 45 46 /** 47 * queue index used to generate transaction ids 48 * @property qidx 49 * @type int 50 * @private 51 */ 52 qidx=0, 53 54 /** 55 * node index used to generate unique node ids 56 * @property nidx 57 * @type int 58 * @private 59 */ 60 nidx=0, 61 62 /** 63 * interal property used to prevent multiple simultaneous purge 64 * processes 65 * @property purging 66 * @type boolean 67 * @private 68 */ 69 _purging=false, 70 71 ua=YAHOO.env.ua, 72 73 lang=YAHOO.lang, 74 75 _fail, 76 _purge, 77 _track, 78 79 /** 80 * Generates an HTML element, this is not appended to a document 81 * @method _node 82 * @param type {string} the type of element 83 * @param attr {string} the attributes 84 * @param win {Window} optional window to create the element in 85 * @return {HTMLElement} the generated node 86 * @private 87 */ 88 _node = function(type, attr, win) { 89 var w = win || window, d=w.document, n=d.createElement(type), i; 90 91 for (i in attr) { 92 if (attr.hasOwnProperty(i)) { 93 n.setAttribute(i, attr[i]); 94 } 95 } 96 97 return n; 98 }, 99 100 /** 101 * Generates a link node 102 * @method _linkNode 103 * @param url {string} the url for the css file 104 * @param win {Window} optional window to create the node in 105 * @return {HTMLElement} the generated node 106 * @private 107 */ 108 _linkNode = function(url, win, attributes) { 109 110 var o = { 111 id: "yui__dyn_" + (nidx++), 112 type: "text/css", 113 rel: "stylesheet", 114 href: url 115 }; 116 117 if (attributes) { 118 lang.augmentObject(o, attributes); 119 } 120 121 return _node("link", o, win); 122 }, 123 124 /** 125 * Generates a script node 126 * @method _scriptNode 127 * @param url {string} the url for the script file 128 * @param win {Window} optional window to create the node in 129 * @return {HTMLElement} the generated node 130 * @private 131 */ 132 _scriptNode = function(url, win, attributes) { 133 var o = { 134 id: "yui__dyn_" + (nidx++), 135 type: "text/javascript", 136 src: url 137 }; 138 139 if (attributes) { 140 lang.augmentObject(o, attributes); 141 } 142 143 return _node("script", o, win); 144 }, 145 146 /** 147 * Returns the data payload for callback functions 148 * @method _returnData 149 * @private 150 */ 151 _returnData = function(q, msg) { 152 return { 153 tId: q.tId, 154 win: q.win, 155 data: q.data, 156 nodes: q.nodes, 157 msg: msg, 158 purge: function() { 159 _purge(this.tId); 160 } 161 }; 162 }, 163 164 _get = function(nId, tId) { 165 var q = queues[tId], 166 n = (lang.isString(nId)) ? q.win.document.getElementById(nId) : nId; 167 if (!n) { 168 _fail(tId, "target node not found: " + nId); 169 } 170 171 return n; 172 }, 173 174 175 /** 176 * The request is complete, so executing the requester's callback 177 * @method _finish 178 * @param id {string} the id of the request 179 * @private 180 */ 181 _finish = function(id) { 182 YAHOO.log("Finishing transaction " + id); 183 var q = queues[id], msg, context; 184 q.finished = true; 185 186 if (q.aborted) { 187 msg = "transaction " + id + " was aborted"; 188 _fail(id, msg); 189 return; 190 } 191 192 // execute success callback 193 if (q.onSuccess) { 194 context = q.scope || q.win; 195 q.onSuccess.call(context, _returnData(q)); 196 } 197 }, 198 199 /** 200 * Timeout detected 201 * @method _timeout 202 * @param id {string} the id of the request 203 * @private 204 */ 205 _timeout = function(id) { 206 YAHOO.log("Timeout " + id, "info", "get"); 207 var q = queues[id], context; 208 if (q.onTimeout) { 209 context = q.scope || q; 210 q.onTimeout.call(context, _returnData(q)); 211 } 212 }, 213 214 /** 215 * Loads the next item for a given request 216 * @method _next 217 * @param id {string} the id of the request 218 * @param loaded {string} the url that was just loaded, if any 219 * @private 220 */ 221 _next = function(id, loaded) { 222 223 YAHOO.log("_next: " + id + ", loaded: " + loaded, "info", "Get"); 224 225 var q = queues[id], w=q.win, d=w.document, h=d.getElementsByTagName("head")[0], 226 n, msg, url, s, extra; 227 228 if (q.timer) { 229 // Y.log('cancel timer'); 230 q.timer.cancel(); 231 } 232 233 if (q.aborted) { 234 msg = "transaction " + id + " was aborted"; 235 _fail(id, msg); 236 return; 237 } 238 239 if (loaded) { 240 q.url.shift(); 241 if (q.varName) { 242 q.varName.shift(); 243 } 244 } else { 245 // This is the first pass: make sure the url is an array 246 q.url = (lang.isString(q.url)) ? [q.url] : q.url; 247 if (q.varName) { 248 q.varName = (lang.isString(q.varName)) ? [q.varName] : q.varName; 249 } 250 } 251 252 253 if (q.url.length === 0) { 254 // Safari 2.x workaround - There is no way to know when 255 // a script is ready in versions of Safari prior to 3.x. 256 // Adding an extra node reduces the problem, but doesn't 257 // eliminate it completely because the browser executes 258 // them asynchronously. 259 if (q.type === "script" && ua.webkit && ua.webkit < 420 && 260 !q.finalpass && !q.varName) { 261 // Add another script node. This does not guarantee that the 262 // scripts will execute in order, but it does appear to fix the 263 // problem on fast connections more effectively than using an 264 // arbitrary timeout. It is possible that the browser does 265 // block subsequent script execution in this case for a limited 266 // time. 267 extra = _scriptNode(null, q.win, q.attributes); 268 extra.innerHTML='YAHOO.util.Get._finalize("' + id + '");'; 269 q.nodes.push(extra); h.appendChild(extra); 270 271 } else { 272 _finish(id); 273 } 274 275 return; 276 } 277 278 279 url = q.url[0]; 280 281 // if the url is undefined, this is probably a trailing comma problem in IE 282 if (!url) { 283 q.url.shift(); 284 YAHOO.log('skipping empty url'); 285 return _next(id); 286 } 287 288 YAHOO.log("attempting to load " + url, "info", "Get"); 289 290 if (q.timeout) { 291 // Y.log('create timer'); 292 q.timer = lang.later(q.timeout, q, _timeout, id); 293 } 294 295 if (q.type === "script") { 296 n = _scriptNode(url, w, q.attributes); 297 } else { 298 n = _linkNode(url, w, q.attributes); 299 } 300 301 // track this node's load progress 302 _track(q.type, n, id, url, w, q.url.length); 303 304 // add the node to the queue so we can return it to the user supplied callback 305 q.nodes.push(n); 306 307 // add it to the head or insert it before 'insertBefore' 308 if (q.insertBefore) { 309 s = _get(q.insertBefore, id); 310 if (s) { 311 s.parentNode.insertBefore(n, s); 312 } 313 } else { 314 h.appendChild(n); 315 } 316 317 YAHOO.log("Appending node: " + url, "info", "Get"); 318 319 // FireFox does not support the onload event for link nodes, so there is 320 // no way to make the css requests synchronous. This means that the css 321 // rules in multiple files could be applied out of order in this browser 322 // if a later request returns before an earlier one. Safari too. 323 if ((ua.webkit || ua.gecko) && q.type === "css") { 324 _next(id, url); 325 } 326 }, 327 328 /** 329 * Removes processed queues and corresponding nodes 330 * @method _autoPurge 331 * @private 332 */ 333 _autoPurge = function() { 334 335 if (_purging) { 336 return; 337 } 338 339 _purging = true; 340 341 var i, q; 342 343 for (i in queues) { 344 if (queues.hasOwnProperty(i)) { 345 q = queues[i]; 346 if (q.autopurge && q.finished) { 347 _purge(q.tId); 348 delete queues[i]; 349 } 350 } 351 } 352 353 _purging = false; 354 }, 355 356 /** 357 * Saves the state for the request and begins loading 358 * the requested urls 359 * @method queue 360 * @param type {string} the type of node to insert 361 * @param url {string} the url to load 362 * @param opts the hash of options for this request 363 * @private 364 */ 365 _queue = function(type, url, opts) { 366 367 var id = "q" + (qidx++), q; 368 opts = opts || {}; 369 370 if (qidx % YAHOO.util.Get.PURGE_THRESH === 0) { 371 _autoPurge(); 372 } 373 374 queues[id] = lang.merge(opts, { 375 tId: id, 376 type: type, 377 url: url, 378 finished: false, 379 aborted: false, 380 nodes: [] 381 }); 382 383 q = queues[id]; 384 q.win = q.win || window; 385 q.scope = q.scope || q.win; 386 q.autopurge = ("autopurge" in q) ? q.autopurge : 387 (type === "script") ? true : false; 388 389 q.attributes = q.attributes || {}; 390 q.attributes.charset = opts.charset || q.attributes.charset || 'utf-8'; 391 392 lang.later(0, q, _next, id); 393 394 return { 395 tId: id 396 }; 397 }; 398 399 /** 400 * Detects when a node has been loaded. In the case of 401 * script nodes, this does not guarantee that contained 402 * script is ready to use. 403 * @method _track 404 * @param type {string} the type of node to track 405 * @param n {HTMLElement} the node to track 406 * @param id {string} the id of the request 407 * @param url {string} the url that is being loaded 408 * @param win {Window} the targeted window 409 * @param qlength the number of remaining items in the queue, 410 * including this one 411 * @param trackfn {Function} function to execute when finished 412 * the default is _next 413 * @private 414 */ 415 _track = function(type, n, id, url, win, qlength, trackfn) { 416 var f = trackfn || _next, rs, q, a, freq, w, l, i, msg; 417 418 // IE supports the readystatechange event for script and css nodes 419 if (ua.ie) { 420 n.onreadystatechange = function() { 421 rs = this.readyState; 422 if ("loaded" === rs || "complete" === rs) { 423 YAHOO.log(id + " onload " + url, "info", "Get"); 424 n.onreadystatechange = null; 425 f(id, url); 426 } 427 }; 428 429 // webkit prior to 3.x is problemmatic 430 } else if (ua.webkit) { 431 432 if (type === "script") { 433 434 // Safari 3.x supports the load event for script nodes (DOM2) 435 if (ua.webkit >= 420) { 436 437 n.addEventListener("load", function() { 438 YAHOO.log(id + " DOM2 onload " + url, "info", "Get"); 439 f(id, url); 440 }); 441 442 // Nothing can be done with Safari < 3.x except to pause and hope 443 // for the best, particularly after last script is inserted. The 444 // scripts will always execute in the order they arrive, not 445 // necessarily the order in which they were inserted. To support 446 // script nodes with complete reliability in these browsers, script 447 // nodes either need to invoke a function in the window once they 448 // are loaded or the implementer needs to provide a well-known 449 // property that the utility can poll for. 450 } else { 451 // Poll for the existence of the named variable, if it 452 // was supplied. 453 q = queues[id]; 454 if (q.varName) { 455 freq = YAHOO.util.Get.POLL_FREQ; 456 YAHOO.log("Polling for " + q.varName[0]); 457 q.maxattempts = YAHOO.util.Get.TIMEOUT/freq; 458 q.attempts = 0; 459 q._cache = q.varName[0].split("."); 460 q.timer = lang.later(freq, q, function(o) { 461 a = this._cache; 462 l = a.length; 463 w = this.win; 464 for (i=0; i<l; i=i+1) { 465 w = w[a[i]]; 466 if (!w) { 467 // if we have exausted our attempts, give up 468 this.attempts++; 469 if (this.attempts++ > this.maxattempts) { 470 msg = "Over retry limit, giving up"; 471 q.timer.cancel(); 472 _fail(id, msg); 473 } else { 474 YAHOO.log(a[i] + " failed, retrying"); 475 } 476 return; 477 } 478 } 479 480 YAHOO.log("Safari poll complete"); 481 482 q.timer.cancel(); 483 f(id, url); 484 485 }, null, true); 486 } else { 487 lang.later(YAHOO.util.Get.POLL_FREQ, null, f, [id, url]); 488 } 489 } 490 } 491 492 // FireFox and Opera support onload (but not DOM2 in FF) handlers for 493 // script nodes. Opera, but not FF, supports the onload event for link 494 // nodes. 495 } else { 496 n.onload = function() { 497 YAHOO.log(id + " onload " + url, "info", "Get"); 498 f(id, url); 499 }; 500 } 501 }; 502 503 /* 504 * The request failed, execute fail handler with whatever 505 * was accomplished. There isn't a failure case at the 506 * moment unless you count aborted transactions 507 * @method _fail 508 * @param id {string} the id of the request 509 * @private 510 */ 511 _fail = function(id, msg) { 512 YAHOO.log("get failure: " + msg, "warn", "Get"); 513 var q = queues[id], context; 514 // execute failure callback 515 if (q.onFailure) { 516 context = q.scope || q.win; 517 q.onFailure.call(context, _returnData(q, msg)); 518 } 519 }; 520 521 /** 522 * Removes the nodes for the specified queue 523 * @method _purge 524 * @private 525 */ 526 _purge = function(tId) { 527 if (queues[tId]) { 528 529 var q = queues[tId], 530 nodes = q.nodes, 531 l = nodes.length, 532 d = q.win.document, 533 h = d.getElementsByTagName("head")[0], 534 sib, i, node, attr; 535 536 if (q.insertBefore) { 537 sib = _get(q.insertBefore, tId); 538 if (sib) { 539 h = sib.parentNode; 540 } 541 } 542 543 for (i=0; i<l; i=i+1) { 544 node = nodes[i]; 545 if (node.clearAttributes) { 546 node.clearAttributes(); 547 } else { 548 for (attr in node) { 549 if (node.hasOwnProperty(attr)) { 550 delete node[attr]; 551 } 552 } 553 } 554 555 h.removeChild(node); 556 } 557 558 q.nodes = []; 559 } 560 }; 561 562 563 return { 564 565 /** 566 * The default poll freqency in ms, when needed 567 * @property POLL_FREQ 568 * @static 569 * @type int 570 * @default 10 571 */ 572 POLL_FREQ: 10, 573 574 /** 575 * The number of request required before an automatic purge. 576 * property PURGE_THRESH 577 * @static 578 * @type int 579 * @default 20 580 */ 581 PURGE_THRESH: 20, 582 583 /** 584 * The length time to poll for varName when loading a script in 585 * Safari 2.x before the transaction fails. 586 * property TIMEOUT 587 * @static 588 * @type int 589 * @default 2000 590 */ 591 TIMEOUT: 2000, 592 593 /** 594 * Called by the the helper for detecting script load in Safari 595 * @method _finalize 596 * @param id {string} the transaction id 597 * @private 598 */ 599 _finalize: function(id) { 600 YAHOO.log(id + " finalized ", "info", "Get"); 601 lang.later(0, null, _finish, id); 602 }, 603 604 /** 605 * Abort a transaction 606 * @method abort 607 * @param {string|object} either the tId or the object returned from 608 * script() or css() 609 */ 610 abort: function(o) { 611 var id = (lang.isString(o)) ? o : o.tId, 612 q = queues[id]; 613 if (q) { 614 YAHOO.log("Aborting " + id, "info", "Get"); 615 q.aborted = true; 616 } 617 }, 618 619 /** 620 * Fetches and inserts one or more script nodes into the head 621 * of the current document or the document in a specified window. 622 * 623 * @method script 624 * @static 625 * @param url {string|string[]} the url or urls to the script(s) 626 * @param opts {object} Options: 627 * <dl> 628 * <dt>onSuccess</dt> 629 * <dd> 630 * callback to execute when the script(s) are finished loading 631 * The callback receives an object back with the following 632 * data: 633 * <dl> 634 * <dt>win</dt> 635 * <dd>the window the script(s) were inserted into</dd> 636 * <dt>data</dt> 637 * <dd>the data object passed in when the request was made</dd> 638 * <dt>nodes</dt> 639 * <dd>An array containing references to the nodes that were 640 * inserted</dd> 641 * <dt>purge</dt> 642 * <dd>A function that, when executed, will remove the nodes 643 * that were inserted</dd> 644 * <dt> 645 * </dl> 646 * </dd> 647 * <dt>onFailure</dt> 648 * <dd> 649 * callback to execute when the script load operation fails 650 * The callback receives an object back with the following 651 * data: 652 * <dl> 653 * <dt>win</dt> 654 * <dd>the window the script(s) were inserted into</dd> 655 * <dt>data</dt> 656 * <dd>the data object passed in when the request was made</dd> 657 * <dt>nodes</dt> 658 * <dd>An array containing references to the nodes that were 659 * inserted successfully</dd> 660 * <dt>purge</dt> 661 * <dd>A function that, when executed, will remove any nodes 662 * that were inserted</dd> 663 * <dt> 664 * </dl> 665 * </dd> 666 * <dt>onTimeout</dt> 667 * <dd> 668 * callback to execute when a timeout occurs. 669 * The callback receives an object back with the following 670 * data: 671 * <dl> 672 * <dt>win</dt> 673 * <dd>the window the script(s) were inserted into</dd> 674 * <dt>data</dt> 675 * <dd>the data object passed in when the request was made</dd> 676 * <dt>nodes</dt> 677 * <dd>An array containing references to the nodes that were 678 * inserted</dd> 679 * <dt>purge</dt> 680 * <dd>A function that, when executed, will remove the nodes 681 * that were inserted</dd> 682 * <dt> 683 * </dl> 684 * </dd> 685 * <dt>scope</dt> 686 * <dd>the execution context for the callbacks</dd> 687 * <dt>win</dt> 688 * <dd>a window other than the one the utility occupies</dd> 689 * <dt>autopurge</dt> 690 * <dd> 691 * setting to true will let the utilities cleanup routine purge 692 * the script once loaded 693 * </dd> 694 * <dt>data</dt> 695 * <dd> 696 * data that is supplied to the callback when the script(s) are 697 * loaded. 698 * </dd> 699 * <dt>varName</dt> 700 * <dd> 701 * variable that should be available when a script is finished 702 * loading. Used to help Safari 2.x and below with script load 703 * detection. The type of this property should match what was 704 * passed into the url parameter: if loading a single url, a 705 * string can be supplied. If loading multiple scripts, you 706 * must supply an array that contains the variable name for 707 * each script. 708 * </dd> 709 * <dt>insertBefore</dt> 710 * <dd>node or node id that will become the new node's nextSibling</dd> 711 * </dl> 712 * <dt>charset</dt> 713 * <dd>Node charset, deprecated, use 'attributes'</dd> 714 * <dt>attributes</dt> 715 * <dd>A hash of attributes to apply to dynamic nodes.</dd> 716 * <dt>timeout</dt> 717 * <dd>Number of milliseconds to wait before aborting and firing the timeout event</dd> 718 * <pre> 719 * // assumes yahoo, dom, and event are already on the page 720 * YAHOO.util.Get.script( 721 * ["http://yui.yahooapis.com/2.7.0/build/dragdrop/dragdrop-min.js", 722 * "http://yui.yahooapis.com/2.7.0/build/animation/animation-min.js"], { 723 * onSuccess: function(o) { 724 * YAHOO.log(o.data); // foo 725 * new YAHOO.util.DDProxy("dd1"); // also new o.reference("dd1"); would work 726 * this.log("won't cause error because YAHOO is the scope"); 727 * this.log(o.nodes.length === 2) // true 728 * // o.purge(); // optionally remove the script nodes immediately 729 * }, 730 * onFailure: function(o) { 731 * YAHOO.log("transaction failed"); 732 * }, 733 * data: "foo", 734 * timeout: 10000, // 10 second timeout 735 * scope: YAHOO, 736 * // win: otherframe // target another window/frame 737 * autopurge: true // allow the utility to choose when to remove the nodes 738 * }); 739 * </pre> 740 * @return {tId: string} an object containing info about the transaction 741 */ 742 script: function(url, opts) { return _queue("script", url, opts); }, 743 744 /** 745 * Fetches and inserts one or more css link nodes into the 746 * head of the current document or the document in a specified 747 * window. 748 * @method css 749 * @static 750 * @param url {string} the url or urls to the css file(s) 751 * @param opts Options: 752 * <dl> 753 * <dt>onSuccess</dt> 754 * <dd> 755 * callback to execute when the css file(s) are finished loading 756 * The callback receives an object back with the following 757 * data: 758 * <dl>win</dl> 759 * <dd>the window the link nodes(s) were inserted into</dd> 760 * <dt>data</dt> 761 * <dd>the data object passed in when the request was made</dd> 762 * <dt>nodes</dt> 763 * <dd>An array containing references to the nodes that were 764 * inserted</dd> 765 * <dt>purge</dt> 766 * <dd>A function that, when executed, will remove the nodes 767 * that were inserted</dd> 768 * <dt> 769 * </dl> 770 * </dd> 771 * <dt>scope</dt> 772 * <dd>the execution context for the callbacks</dd> 773 * <dt>win</dt> 774 * <dd>a window other than the one the utility occupies</dd> 775 * <dt>data</dt> 776 * <dd> 777 * data that is supplied to the callbacks when the nodes(s) are 778 * loaded. 779 * </dd> 780 * <dt>insertBefore</dt> 781 * <dd>node or node id that will become the new node's nextSibling</dd> 782 * <dt>charset</dt> 783 * <dd>Node charset, deprecated, use 'attributes'</dd> 784 * <dt>attributes</dt> 785 * <dd>A hash of attributes to apply to dynamic nodes.</dd> 786 * </dl> 787 * <pre> 788 * YAHOO.util.Get.css("http://yui.yahooapis.com/2.7.0/build/menu/assets/skins/sam/menu.css"); 789 * </pre> 790 * <pre> 791 * YAHOO.util.Get.css(["http://yui.yahooapis.com/2.7.0/build/menu/assets/skins/sam/menu.css", 792 * "http://yui.yahooapis.com/2.7.0/build/logger/assets/skins/sam/logger.css"]); 793 * </pre> 794 * @return {tId: string} an object containing info about the transaction 795 */ 796 css: function(url, opts) { 797 return _queue("css", url, opts); 798 } 799 }; 800 }(); 801 802 YAHOO.register("get", YAHOO.util.Get, {version: "2.9.0", build: "2800"}); 803 804 }, '2.9.0' ,{"requires": ["yui2-yahoo"]});
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |