Changeset 856065
- Timestamp:
- 02/12/2014 04:02:55 AM (12 years ago)
- Location:
- headwp/trunk
- Files:
-
- 17 added
- 3 edited
-
head-js-wp.php (modified) (1 diff)
-
inc (added)
-
inc/class-head-js-wp.php (added)
-
inc/class-model-head-js-wp.php (added)
-
inc/class-shortcodes-head-js-wp.php (added)
-
inc/class-view-head-js-wp.php (added)
-
inc/templates (added)
-
inc/templates/head-init-template.php (added)
-
inc/templates/head-load-template.php (added)
-
inc/templates/head-ready-template.php (added)
-
inc/templates/inline-script-template.php (added)
-
inc/templates/load-async-script-template.php (added)
-
inc/templates/min (added)
-
inc/templates/min/head-init-template.php (added)
-
inc/templates/min/head-load-template.php (added)
-
inc/templates/min/head-ready-template.php (added)
-
inc/templates/min/inline-script-template.php (added)
-
inc/templates/min/load-async-script-template.php (added)
-
js/libs/head.load.js (modified) (1 diff)
-
readme.txt (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
headwp/trunk/head-js-wp.php
r701136 r856065 5 5 Description: A plugin to load footer scripts with head.js 6 6 Author: Kyle Reicks 7 Version: 1.07 Version: 2.0.0 8 8 Author URI: http://github.com/kylereicks/ 9 9 */ 10 10 11 if(!class_exists('Head_js_wp')){ 12 class Head_js_wp{ 11 define('HEAD_JS_WP_PATH', plugin_dir_path(__FILE__)); 12 define('HEAD_JS_WP_URL', plugins_url('/', __FILE__)); 13 define('HEAD_JS_WP_VERSION', '2.0.0'); 14 define('HEAD_JS_VERSION', '1.0.3'); 13 15 14 function __construct(){ 15 if(!is_admin()){ 16 add_action('wp_enqueue_scripts', array($this, 'add_header_js_to_head')); 17 remove_action('wp_print_footer_scripts', '_wp_footer_scripts'); 18 add_action('wp_print_footer_scripts', array($this, 'print_scripts_with_header_js')); 19 } 20 } 16 require_once(HEAD_JS_WP_PATH . 'inc/class-head-js-wp.php'); 21 17 22 function add_header_js_to_head(){ 23 if(!wp_script_is('head-js')){ 24 wp_register_script('head-js', plugins_url('/js/libs/head.load.js', __FILE__)); 25 } 26 } 18 register_deactivation_hook(__FILE__, array('Head_js_wp', 'deactivate')); 27 19 28 function print_scripts_with_header_js(){ 29 global $wp_scripts; 30 31 print_late_styles(); 32 33 if(!empty($wp_scripts->queue)){ 34 $wp_scripts->all_deps($wp_scripts->queue); 35 } 36 37 if(!empty($wp_scripts->to_do)){ 38 $wp_scripts->do_item('head-js'); 39 40 foreach($wp_scripts->to_do as $handle){ 41 $wp_scripts->print_extra_script($handle); 42 } 43 44 $script_queues = $this->queue_scripts($wp_scripts); 45 46 echo '<script>' . "\n" . 'head'; 47 foreach($script_queues as $queue){ 48 echo "\n" . '.js({'; 49 foreach($queue as $number => $script){ 50 $ending = (count($queue) === $number + 1) ? '})' : "},\n{"; 51 $version = ($wp_scripts->registered[$script]->ver) ? '?ver=' . $wp_scripts->registered[$script]->ver : ""; 52 $base_url = (preg_match('/^\//', $wp_scripts->registered[$script]->src)) ? $wp_scripts->base_url : ''; 53 echo str_replace('-', '_', $script) . " : '" . $base_url . $wp_scripts->registered[$script]->src . $version . "'" . $ending; 54 $wp_scripts->done[] = $script; 55 $wp_scripts->to_do = array_merge(array_diff($wp_scripts->to_do, array($script))); 56 } 57 } 58 echo ';' . "\n" . '</script>' . "\n"; 59 return true; 60 }else{ 61 return false; 62 } 63 } 64 65 private function queue_scripts($wp_scripts){ 66 $script_queues = array(); 67 68 foreach($wp_scripts->to_do as $script){ 69 if(empty($wp_scripts->registered[$script]->deps)){ 70 $script_queues[] = array( 71 $script 72 ); 73 }else{ 74 foreach($script_queues as $number => $queue){ 75 foreach($queue as $queue_script){ 76 if(in_array($queue_script, $wp_scripts->registered[$script]->deps) && !in_array($script, $script_queues[$number])){ 77 $script_queues[$number][] = $script; 78 } 79 } 80 } 81 } 82 } 83 84 foreach($script_queues as $number => $queue){ 85 foreach($script_queues as $number_check => $queue_check){ 86 if($number > $number_check){ 87 $intersect = array_intersect($script_queues[$number], $script_queues[$number_check]); 88 if(!empty($intersect)){ 89 $script_queues[$number] = array_diff($script_queues[$number], $intersect); 90 $script_queues[$number] = array_merge($script_queues[$number], $script_queues[$number_check]); 91 unset($script_queues[$number_check]); 92 } 93 } 94 } 95 } 96 return $script_queues; 97 } 98 }/* End class Head_js_wp */ 99 $head_js_wp = new Head_js_wp(); 100 } 101 /* End file head-js-wp.php */ 20 Head_js_wp::get_instance(); -
headwp/trunk/js/libs/head.load.js
r701136 r856065 1 (function(f,w){function m(){}function g(a,b){if(a){"object"===typeof a&&(a=[].slice.call(a));for(var c=0,d=a.length;c<d;c++)b.call(a,a[c],c)}}function v(a,b){var c=Object.prototype.toString.call(b).slice(8,-1);return b!==w&&null!==b&&c===a}function k(a){return v("Function",a)}function h(a){a=a||m;a._done||(a(),a._done=1)}function n(a){var b={};if("object"===typeof a)for(var c in a)a[c]&&(b={name:c,url:a[c]});else b=a.split("/"),b=b[b.length-1],c=b.indexOf("?"),b={name:-1!==c?b.substring(0,c):b,url:a}; 2 return(a=p[b.name])&&a.url===b.url?a:p[b.name]=b}function q(a){var a=a||p,b;for(b in a)if(a.hasOwnProperty(b)&&a[b].state!==r)return!1;return!0}function s(a,b){b=b||m;a.state===r?b():a.state===x?d.ready(a.name,b):a.state===y?a.onpreload.push(function(){s(a,b)}):(a.state=x,z(a,function(){a.state=r;b();g(l[a.name],function(a){h(a)});j&&q()&&g(l.ALL,function(a){h(a)})}))}function z(a,b){var b=b||m,c;/\.css[^\.]*$/.test(a.url)?(c=e.createElement("link"),c.type="text/"+(a.type||"css"),c.rel="stylesheet", 3 c.href=a.url):(c=e.createElement("script"),c.type="text/"+(a.type||"javascript"),c.src=a.url);c.onload=c.onreadystatechange=function(a){a=a||f.event;if("load"===a.type||/loaded|complete/.test(c.readyState)&&(!e.documentMode||9>e.documentMode))c.onload=c.onreadystatechange=c.onerror=null,b()};c.onerror=function(){c.onload=c.onreadystatechange=c.onerror=null;b()};c.async=!1;c.defer=!1;var d=e.head||e.getElementsByTagName("head")[0];d.insertBefore(c,d.lastChild)}function i(){e.body?j||(j=!0,g(A,function(a){h(a)})): 4 (f.clearTimeout(d.readyTimeout),d.readyTimeout=f.setTimeout(i,50))}function t(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",t,!1),i()):"complete"===e.readyState&&(e.detachEvent("onreadystatechange",t),i())}var e=f.document,A=[],B=[],l={},p={},E="async"in e.createElement("script")||"MozAppearance"in e.documentElement.style||f.opera,C,j,D=f.head_conf&&f.head_conf.head||"head",d=f[D]=f[D]||function(){d.ready.apply(null,arguments)},y=1,x=3,r=4;d.load=E?function(){var a=arguments,b=a[a.length- 5 1],c={};k(b)||(b=null);g(a,function(d,e){d!==b&&(d=n(d),c[d.name]=d,s(d,b&&e===a.length-2?function(){q(c)&&h(b)}:null))});return d}:function(){var a=arguments,b=[].slice.call(a,1),c=b[0];if(!C)return B.push(function(){d.load.apply(null,a)}),d;c?(g(b,function(a){if(!k(a)){var b=n(a);b.state===w&&(b.state=y,b.onpreload=[],z({url:b.url,type:"cache"},function(){b.state=2;g(b.onpreload,function(a){a.call()})}))}}),s(n(a[0]),k(c)?c:function(){d.load.apply(null,b)})):s(n(a[0]));return d};d.js=d.load;d.test= 6 function(a,b,c,e){a="object"===typeof a?a:{test:a,success:b?v("Array",b)?b:[b]:!1,failure:c?v("Array",c)?c:[c]:!1,callback:e||m};(b=!!a.test)&&a.success?(a.success.push(a.callback),d.load.apply(null,a.success)):!b&&a.failure?(a.failure.push(a.callback),d.load.apply(null,a.failure)):e();return d};d.ready=function(a,b){if(a===e)return j?h(b):A.push(b),d;k(a)&&(b=a,a="ALL");if("string"!==typeof a||!k(b))return d;var c=p[a];if(c&&c.state===r||"ALL"===a&&q()&&j)return h(b),d;(c=l[a])?c.push(b):l[a]=[b]; 7 return d};d.ready(e,function(){q()&&g(l.ALL,function(a){h(a)});d.feature&&d.feature("domloaded",!0)});if("complete"===e.readyState)i();else if(e.addEventListener)e.addEventListener("DOMContentLoaded",t,!1),f.addEventListener("load",i,!1);else{e.attachEvent("onreadystatechange",t);f.attachEvent("onload",i);var u=!1;try{u=null==f.frameElement&&e.documentElement}catch(F){}u&&u.doScroll&&function b(){if(!j){try{u.doScroll("left")}catch(c){f.clearTimeout(d.readyTimeout);d.readyTimeout=f.setTimeout(b,50); 8 return}i()}}()}setTimeout(function(){C=!0;g(B,function(b){b()})},300)})(window); 1 ///#source 1 1 /src/1.0.0/load.js 2 /*! head.load - v1.0.3 */ 3 /* 4 * HeadJS The only script in your <HEAD> 5 * Author Tero Piirainen (tipiirai) 6 * Maintainer Robert Hoffmann (itechnology) 7 * License MIT / http://bit.ly/mit-license 8 * WebSite http://headjs.com 9 */ 10 (function (win, undefined) { 11 "use strict"; 12 13 //#region variables 14 var doc = win.document, 15 domWaiters = [], 16 handlers = {}, // user functions waiting for events 17 assets = {}, // loadable items in various states 18 isAsync = "async" in doc.createElement("script") || "MozAppearance" in doc.documentElement.style || win.opera, 19 isDomReady, 20 21 /*** public API ***/ 22 headVar = win.head_conf && win.head_conf.head || "head", 23 api = win[headVar] = (win[headVar] || function () { api.ready.apply(null, arguments); }), 24 25 // states 26 PRELOADING = 1, 27 PRELOADED = 2, 28 LOADING = 3, 29 LOADED = 4; 30 //#endregion 31 32 //#region PRIVATE functions 33 34 //#region Helper functions 35 function noop() { 36 // does nothing 37 } 38 39 function each(arr, callback) { 40 if (!arr) { 41 return; 42 } 43 44 // arguments special type 45 if (typeof arr === "object") { 46 arr = [].slice.call(arr); 47 } 48 49 // do the job 50 for (var i = 0, l = arr.length; i < l; i++) { 51 callback.call(arr, arr[i], i); 52 } 53 } 54 55 /* A must read: http://bonsaiden.github.com/JavaScript-Garden 56 ************************************************************/ 57 function is(type, obj) { 58 var clas = Object.prototype.toString.call(obj).slice(8, -1); 59 return obj !== undefined && obj !== null && clas === type; 60 } 61 62 function isFunction(item) { 63 return is("Function", item); 64 } 65 66 function isArray(item) { 67 return is("Array", item); 68 } 69 70 function toLabel(url) { 71 ///<summary>Converts a url to a file label</summary> 72 var items = url.split("/"), 73 name = items[items.length - 1], 74 i = name.indexOf("?"); 75 76 return i !== -1 ? name.substring(0, i) : name; 77 } 78 79 // INFO: this look like a "im triggering callbacks all over the place, but only wanna run it one time function" ..should try to make everything work without it if possible 80 // INFO: Even better. Look into promises/defered's like jQuery is doing 81 function one(callback) { 82 ///<summary>Execute a callback only once</summary> 83 callback = callback || noop; 84 85 if (callback._done) { 86 return; 87 } 88 89 callback(); 90 callback._done = 1; 91 } 92 //#endregion 93 94 function conditional(test, success, failure, callback) { 95 ///<summary> 96 /// INFO: use cases: 97 /// head.test(condition, null , "file.NOk" , callback); 98 /// head.test(condition, "fileOk.js", null , callback); 99 /// head.test(condition, "fileOk.js", "file.NOk" , callback); 100 /// head.test(condition, "fileOk.js", ["file.NOk", "file.NOk"], callback); 101 /// head.test({ 102 /// test : condition, 103 /// success : [{ label1: "file1Ok.js" }, { label2: "file2Ok.js" }], 104 /// failure : [{ label1: "file1NOk.js" }, { label2: "file2NOk.js" }], 105 /// callback: callback 106 /// ); 107 /// head.test({ 108 /// test : condition, 109 /// success : ["file1Ok.js" , "file2Ok.js"], 110 /// failure : ["file1NOk.js", "file2NOk.js"], 111 /// callback: callback 112 /// ); 113 ///</summary> 114 var obj = (typeof test === "object") ? test : { 115 test: test, 116 success: !!success ? isArray(success) ? success : [success] : false, 117 failure: !!failure ? isArray(failure) ? failure : [failure] : false, 118 callback: callback || noop 119 }; 120 121 // Test Passed ? 122 var passed = !!obj.test; 123 124 // Do we have a success case 125 if (passed && !!obj.success) { 126 obj.success.push(obj.callback); 127 api.load.apply(null, obj.success); 128 } 129 // Do we have a fail case 130 else if (!passed && !!obj.failure) { 131 obj.failure.push(obj.callback); 132 api.load.apply(null, obj.failure); 133 } 134 else { 135 callback(); 136 } 137 138 return api; 139 } 140 141 function getAsset(item) { 142 ///<summary> 143 /// Assets are in the form of 144 /// { 145 /// name : label, 146 /// url : url, 147 /// state: state 148 /// } 149 ///</summary> 150 var asset = {}; 151 152 if (typeof item === "object") { 153 for (var label in item) { 154 if (!!item[label]) { 155 asset = { 156 name: label, 157 url : item[label] 158 }; 159 } 160 } 161 } 162 else { 163 asset = { 164 name: toLabel(item), 165 url : item 166 }; 167 } 168 169 // is the item already existant 170 var existing = assets[asset.name]; 171 if (existing && existing.url === asset.url) { 172 return existing; 173 } 174 175 assets[asset.name] = asset; 176 return asset; 177 } 178 179 function allLoaded(items) { 180 items = items || assets; 181 182 for (var name in items) { 183 if (items.hasOwnProperty(name) && items[name].state !== LOADED) { 184 return false; 185 } 186 } 187 188 return true; 189 } 190 191 function onPreload(asset) { 192 asset.state = PRELOADED; 193 194 each(asset.onpreload, function (afterPreload) { 195 afterPreload.call(); 196 }); 197 } 198 199 function preLoad(asset, callback) { 200 if (asset.state === undefined) { 201 202 asset.state = PRELOADING; 203 asset.onpreload = []; 204 205 loadAsset({ url: asset.url, type: "cache" }, function () { 206 onPreload(asset); 207 }); 208 } 209 } 210 211 function apiLoadHack() { 212 /// <summary>preload with text/cache hack 213 /// 214 /// head.load("http://domain.com/file.js","http://domain.com/file.js", callBack) 215 /// head.load(["http://domain.com/file.js","http://domain.com/file.js"], callBack) 216 /// head.load({ label1: "http://domain.com/file.js" }, { label2: "http://domain.com/file.js" }, callBack) 217 /// head.load([{ label1: "http://domain.com/file.js" }, { label2: "http://domain.com/file.js" }], callBack) 218 /// </summary> 219 var args = arguments, 220 callback = args[args.length - 1], 221 rest = [].slice.call(args, 1), 222 next = rest[0]; 223 224 if (!isFunction(callback)) { 225 callback = null; 226 } 227 228 // if array, repush as args 229 if (isArray(args[0])) { 230 args[0].push(callback); 231 api.load.apply(null, args[0]); 232 233 return api; 234 } 235 236 // multiple arguments 237 if (!!next) { 238 /* Preload with text/cache hack (not good!) 239 * http://blog.getify.com/on-script-loaders/ 240 * http://www.nczonline.net/blog/2010/12/21/thoughts-on-script-loaders/ 241 * If caching is not configured correctly on the server, then items could load twice ! 242 *************************************************************************************/ 243 each(rest, function (item) { 244 // item is not a callback or empty string 245 if (!isFunction(item) && !!item) { 246 preLoad(getAsset(item)); 247 } 248 }); 249 250 // execute 251 load(getAsset(args[0]), isFunction(next) ? next : function () { 252 api.load.apply(null, rest); 253 }); 254 } 255 else { 256 // single item 257 load(getAsset(args[0])); 258 } 259 260 return api; 261 } 262 263 function apiLoadAsync() { 264 ///<summary> 265 /// simply load and let browser take care of ordering 266 /// 267 /// head.load("http://domain.com/file.js","http://domain.com/file.js", callBack) 268 /// head.load(["http://domain.com/file.js","http://domain.com/file.js"], callBack) 269 /// head.load({ label1: "http://domain.com/file.js" }, { label2: "http://domain.com/file.js" }, callBack) 270 /// head.load([{ label1: "http://domain.com/file.js" }, { label2: "http://domain.com/file.js" }], callBack) 271 ///</summary> 272 var args = arguments, 273 callback = args[args.length - 1], 274 items = {}; 275 276 if (!isFunction(callback)) { 277 callback = null; 278 } 279 280 // if array, repush as args 281 if (isArray(args[0])) { 282 args[0].push(callback); 283 api.load.apply(null, args[0]); 284 285 return api; 286 } 287 288 // JRH 262#issuecomment-26288601 289 // First populate the items array. 290 // When allLoaded is called, all items will be populated. 291 // Issue when lazy loaded, the callback can execute early. 292 each(args, function (item, i) { 293 if (item !== callback) { 294 item = getAsset(item); 295 items[item.name] = item; 296 } 297 }); 298 299 each(args, function (item, i) { 300 if (item !== callback) { 301 item = getAsset(item); 302 303 load(item, function () { 304 if (allLoaded(items)) { 305 one(callback); 306 } 307 }); 308 } 309 }); 310 311 return api; 312 } 313 314 function load(asset, callback) { 315 ///<summary>Used with normal loading logic</summary> 316 callback = callback || noop; 317 318 if (asset.state === LOADED) { 319 callback(); 320 return; 321 } 322 323 // INFO: why would we trigger a ready event when its not really loaded yet ? 324 if (asset.state === LOADING) { 325 api.ready(asset.name, callback); 326 return; 327 } 328 329 if (asset.state === PRELOADING) { 330 asset.onpreload.push(function () { 331 load(asset, callback); 332 }); 333 return; 334 } 335 336 asset.state = LOADING; 337 338 loadAsset(asset, function () { 339 asset.state = LOADED; 340 341 callback(); 342 343 // handlers for this asset 344 each(handlers[asset.name], function (fn) { 345 one(fn); 346 }); 347 348 // dom is ready & no assets are queued for loading 349 // INFO: shouldn't we be doing the same test above ? 350 if (isDomReady && allLoaded()) { 351 each(handlers.ALL, function (fn) { 352 one(fn); 353 }); 354 } 355 }); 356 } 357 358 function getExtension(url) { 359 url = url || ""; 360 361 var items = url.split("?")[0].split("."); 362 return items[items.length-1].toLowerCase(); 363 } 364 365 /* Parts inspired from: https://github.com/cujojs/curl 366 ******************************************************/ 367 function loadAsset(asset, callback) { 368 callback = callback || noop; 369 370 function error(event) { 371 event = event || win.event; 372 373 // release event listeners 374 ele.onload = ele.onreadystatechange = ele.onerror = null; 375 376 // do callback 377 callback(); 378 379 // need some more detailed error handling here 380 } 381 382 function process(event) { 383 event = event || win.event; 384 385 // IE 7/8 (2 events on 1st load) 386 // 1) event.type = readystatechange, s.readyState = loading 387 // 2) event.type = readystatechange, s.readyState = loaded 388 389 // IE 7/8 (1 event on reload) 390 // 1) event.type = readystatechange, s.readyState = complete 391 392 // event.type === 'readystatechange' && /loaded|complete/.test(s.readyState) 393 394 // IE 9 (3 events on 1st load) 395 // 1) event.type = readystatechange, s.readyState = loading 396 // 2) event.type = readystatechange, s.readyState = loaded 397 // 3) event.type = load , s.readyState = loaded 398 399 // IE 9 (2 events on reload) 400 // 1) event.type = readystatechange, s.readyState = complete 401 // 2) event.type = load , s.readyState = complete 402 403 // event.type === 'load' && /loaded|complete/.test(s.readyState) 404 // event.type === 'readystatechange' && /loaded|complete/.test(s.readyState) 405 406 // IE 10 (3 events on 1st load) 407 // 1) event.type = readystatechange, s.readyState = loading 408 // 2) event.type = load , s.readyState = complete 409 // 3) event.type = readystatechange, s.readyState = loaded 410 411 // IE 10 (3 events on reload) 412 // 1) event.type = readystatechange, s.readyState = loaded 413 // 2) event.type = load , s.readyState = complete 414 // 3) event.type = readystatechange, s.readyState = complete 415 416 // event.type === 'load' && /loaded|complete/.test(s.readyState) 417 // event.type === 'readystatechange' && /complete/.test(s.readyState) 418 419 // Other Browsers (1 event on 1st load) 420 // 1) event.type = load, s.readyState = undefined 421 422 // Other Browsers (1 event on reload) 423 // 1) event.type = load, s.readyState = undefined 424 425 // event.type == 'load' && s.readyState = undefined 426 427 // !doc.documentMode is for IE6/7, IE8+ have documentMode 428 if (event.type === "load" || (/loaded|complete/.test(ele.readyState) && (!doc.documentMode || doc.documentMode < 9))) { 429 // remove timeouts 430 win.clearTimeout(asset.errorTimeout); 431 win.clearTimeout(asset.cssTimeout); 432 433 // release event listeners 434 ele.onload = ele.onreadystatechange = ele.onerror = null; 435 436 // do callback 437 callback(); 438 } 439 } 440 441 function isCssLoaded() { 442 // should we test again ? 20 retries = 5secs ..after that, the callback will be triggered by the error handler at 7secs 443 if (asset.state !== LOADED && asset.cssRetries <= 20) { 444 445 // loop through stylesheets 446 for (var i = 0, l = doc.styleSheets.length; i < l; i++) { 447 // do we have a match ? 448 // we need to tests agains ele.href and not asset.url, because a local file will be assigned the full http path on a link element 449 if (doc.styleSheets[i].href === ele.href) { 450 process({ "type": "load" }); 451 return; 452 } 453 } 454 455 // increment & try again 456 asset.cssRetries++; 457 asset.cssTimeout = win.setTimeout(isCssLoaded, 250); 458 } 459 } 460 461 var ele; 462 var ext = getExtension(asset.url); 463 464 if (ext === "css") { 465 ele = doc.createElement("link"); 466 ele.type = "text/" + (asset.type || "css"); 467 ele.rel = "stylesheet"; 468 ele.href = asset.url; 469 470 /* onload supported for CSS on unsupported browsers 471 * Safari windows 5.1.7, FF < 10 472 */ 473 474 // Set counter to zero 475 asset.cssRetries = 0; 476 asset.cssTimeout = win.setTimeout(isCssLoaded, 500); 477 } 478 else { 479 ele = doc.createElement("script"); 480 ele.type = "text/" + (asset.type || "javascript"); 481 ele.src = asset.url; 482 } 483 484 ele.onload = ele.onreadystatechange = process; 485 ele.onerror = error; 486 487 /* Good read, but doesn't give much hope ! 488 * http://blog.getify.com/on-script-loaders/ 489 * http://www.nczonline.net/blog/2010/12/21/thoughts-on-script-loaders/ 490 * https://hacks.mozilla.org/2009/06/defer/ 491 */ 492 493 // ASYNC: load in parallel and execute as soon as possible 494 ele.async = false; 495 // DEFER: load in parallel but maintain execution order 496 ele.defer = false; 497 498 // timout for asset loading 499 asset.errorTimeout = win.setTimeout(function () { 500 error({ type: "timeout" }); 501 }, 7e3); 502 503 // use insertBefore to keep IE from throwing Operation Aborted (thx Bryan Forbes!) 504 var head = doc.head || doc.getElementsByTagName("head")[0]; 505 506 // but insert at end of head, because otherwise if it is a stylesheet, it will not override values 507 head.insertBefore(ele, head.lastChild); 508 } 509 510 /* Parts inspired from: https://github.com/jrburke/requirejs 511 ************************************************************/ 512 function init() { 513 var items = doc.getElementsByTagName("script"); 514 515 // look for a script with a data-head-init attribute 516 for (var i = 0, l = items.length; i < l; i++) { 517 var dataMain = items[i].getAttribute("data-headjs-load"); 518 if (!!dataMain) { 519 api.load(dataMain); 520 return; 521 } 522 } 523 } 524 525 function ready(key, callback) { 526 ///<summary> 527 /// INFO: use cases: 528 /// head.ready(callBack); 529 /// head.ready(document , callBack); 530 /// head.ready("file.js", callBack); 531 /// head.ready("label" , callBack); 532 /// head.ready(["label1", "label2"], callback); 533 ///</summary> 534 535 // DOM ready check: head.ready(document, function() { }); 536 if (key === doc) { 537 if (isDomReady) { 538 one(callback); 539 } 540 else { 541 domWaiters.push(callback); 542 } 543 544 return api; 545 } 546 547 // shift arguments 548 if (isFunction(key)) { 549 callback = key; 550 key = "ALL"; // holds all callbacks that where added without labels: ready(callBack) 551 } 552 553 // queue all items from key and return. The callback will be executed if all items from key are already loaded. 554 if (isArray(key)) { 555 var items = {}; 556 557 each(key, function (item) { 558 items[item] = assets[item]; 559 560 api.ready(item, function() { 561 if (allLoaded(items)) { 562 one(callback); 563 } 564 }); 565 }); 566 567 return api; 568 } 569 570 // make sure arguments are sane 571 if (typeof key !== "string" || !isFunction(callback)) { 572 return api; 573 } 574 575 // this can also be called when we trigger events based on filenames & labels 576 var asset = assets[key]; 577 578 // item already loaded --> execute and return 579 if (asset && asset.state === LOADED || key === "ALL" && allLoaded() && isDomReady) { 580 one(callback); 581 return api; 582 } 583 584 var arr = handlers[key]; 585 if (!arr) { 586 arr = handlers[key] = [callback]; 587 } 588 else { 589 arr.push(callback); 590 } 591 592 return api; 593 } 594 595 /* Mix of stuff from jQuery & IEContentLoaded 596 * http://dev.w3.org/html5/spec/the-end.html#the-end 597 ***************************************************/ 598 function domReady() { 599 // Make sure body exists, at least, in case IE gets a little overzealous (jQuery ticket #5443). 600 if (!doc.body) { 601 // let's not get nasty by setting a timeout too small.. (loop mania guaranteed if assets are queued) 602 win.clearTimeout(api.readyTimeout); 603 api.readyTimeout = win.setTimeout(domReady, 50); 604 return; 605 } 606 607 if (!isDomReady) { 608 isDomReady = true; 609 610 init(); 611 each(domWaiters, function (fn) { 612 one(fn); 613 }); 614 } 615 } 616 617 function domContentLoaded() { 618 // W3C 619 if (doc.addEventListener) { 620 doc.removeEventListener("DOMContentLoaded", domContentLoaded, false); 621 domReady(); 622 } 623 624 // IE 625 else if (doc.readyState === "complete") { 626 // we're here because readyState === "complete" in oldIE 627 // which is good enough for us to call the dom ready! 628 doc.detachEvent("onreadystatechange", domContentLoaded); 629 domReady(); 630 } 631 } 632 633 // Catch cases where ready() is called after the browser event has already occurred. 634 // we once tried to use readyState "interactive" here, but it caused issues like the one 635 // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 636 if (doc.readyState === "complete") { 637 domReady(); 638 } 639 640 // W3C 641 else if (doc.addEventListener) { 642 doc.addEventListener("DOMContentLoaded", domContentLoaded, false); 643 644 // A fallback to window.onload, that will always work 645 win.addEventListener("load", domReady, false); 646 } 647 648 // IE 649 else { 650 // Ensure firing before onload, maybe late but safe also for iframes 651 doc.attachEvent("onreadystatechange", domContentLoaded); 652 653 // A fallback to window.onload, that will always work 654 win.attachEvent("onload", domReady); 655 656 // If IE and not a frame 657 // continually check to see if the document is ready 658 var top = false; 659 660 try { 661 top = !win.frameElement && doc.documentElement; 662 } catch (e) { } 663 664 if (top && top.doScroll) { 665 (function doScrollCheck() { 666 if (!isDomReady) { 667 try { 668 // Use the trick by Diego Perini 669 // http://javascript.nwbox.com/IEContentLoaded/ 670 top.doScroll("left"); 671 } catch (error) { 672 // let's not get nasty by setting a timeout too small.. (loop mania guaranteed if assets are queued) 673 win.clearTimeout(api.readyTimeout); 674 api.readyTimeout = win.setTimeout(doScrollCheck, 50); 675 return; 676 } 677 678 // and execute any waiting functions 679 domReady(); 680 } 681 }()); 682 } 683 } 684 //#endregion 685 686 //#region Public Exports 687 // INFO: determine which method to use for loading 688 api.load = api.js = isAsync ? apiLoadAsync : apiLoadHack; 689 api.test = conditional; 690 api.ready = ready; 691 //#endregion 692 693 //#region INIT 694 // perform this when DOM is ready 695 api.ready(doc, function () { 696 if (allLoaded()) { 697 each(handlers.ALL, function (callback) { 698 one(callback); 699 }); 700 } 701 702 if (api.feature) { 703 api.feature("domloaded", true); 704 } 705 }); 706 //#endregion 707 }(window)); -
headwp/trunk/readme.txt
r701136 r856065 4 4 Tags: script loading, asynchronous, javascript, async, headJS, head.js, enqueue, wp_enqueue_script 5 5 Requires at least: 3.2 6 Tested up to: 3. 5.17 Stable tag: 1.06 Tested up to: 3.8.1 7 Stable tag: 2.0.0 8 8 License: GPLv2 or later 9 9 License URI: http://www.gnu.org/licenses/gpl-2.0.html 10 10 11 A plugin to load all footer scripts with [head.js](https://github.com/headjs/headjs).11 A plugin to load all footer scripts and styles with [head.js](https://github.com/headjs/headjs). 12 12 13 13 == Description == 14 14 15 Head.js is a script to asynchronously load and optionally asynchronously execute javascriptassets.15 Head.js is a script to asynchronously load and manage dependencies of javascript and CSS assets. 16 16 17 This plugin loads the scripts enqueued in footer with the head.js loader. All of the footer scripts are loaded asynchronously and any scripts that do not share dependencies are executed asynchronously while scripts that share dependencies are executed in order.17 This plugin loads the scripts and styles enqueued in footer with the head.js loader. It does not include head.js' feature detection. 18 18 19 Head. WPassumes that scripts are loaded via `wp_enqueue_script()` and that any script enqueued in the `<head>` intends to be loaded before the rest of the page.19 Head.js.wp assumes that scripts are loaded via `wp_enqueue_script()` and that any script enqueued in the `<head>` intends to be loaded before the rest of the page. 20 20 21 21 == Installation == … … 48 48 == Changelog == 49 49 50 = 2.0.0 = 51 * A complete rewrite. It really is much nicer now. 52 * Update to head.js version 1.0.3 53 50 54 = 1.0 = 51 55 * Release 1.0. … … 53 57 == Upgrade Notice == 54 58 55 = 1.0 =56 This is the initial public release.59 = 2.0 = 60 This is a complete rewrite of the 1.0 release. I don't forsee any upgrading problems, but if you have made any customizations to the plugin or it's functionality, please test before updating a live site.
Note: See TracChangeset
for help on using the changeset viewer.