OLD | NEW |
(Empty) | |
| 1 |
| 2 (function() { |
| 3 |
| 4 Polymer('core-shared-lib',{ |
| 5 |
| 6 notifyEvent: 'core-shared-lib-load', |
| 7 |
| 8 ready: function() { |
| 9 if (!this.url && this.defaultUrl) { |
| 10 this.url = this.defaultUrl; |
| 11 } |
| 12 }, |
| 13 |
| 14 urlChanged: function() { |
| 15 require(this.url, this, this.callbackName); |
| 16 }, |
| 17 |
| 18 provide: function() { |
| 19 this.async('notify'); |
| 20 }, |
| 21 |
| 22 notify: function() { |
| 23 this.fire(this.notifyEvent, arguments); |
| 24 } |
| 25 |
| 26 }); |
| 27 |
| 28 var apiMap = {}; |
| 29 |
| 30 function require(url, notifiee, callbackName) { |
| 31 // make hashable string form url |
| 32 var name = nameFromUrl(url); |
| 33 // lookup existing loader instance |
| 34 var loader = apiMap[name]; |
| 35 // create a loader as needed |
| 36 if (!loader) { |
| 37 loader = apiMap[name] = new Loader(name, url, callbackName); |
| 38 } |
| 39 loader.requestNotify(notifiee); |
| 40 } |
| 41 |
| 42 function nameFromUrl(url) { |
| 43 return url.replace(/[\:\/\%\?\&\.\=\-]/g, '_') + '_api'; |
| 44 } |
| 45 |
| 46 var Loader = function(name, url, callbackName) { |
| 47 this.instances = []; |
| 48 this.callbackName = callbackName; |
| 49 if (this.callbackName) { |
| 50 window[this.callbackName] = this.success.bind(this); |
| 51 } else { |
| 52 if (url.indexOf(this.callbackMacro) >= 0) { |
| 53 this.callbackName = name + '_loaded'; |
| 54 window[this.callbackName] = this.success.bind(this); |
| 55 url = url.replace(this.callbackMacro, this.callbackName); |
| 56 } else { |
| 57 // TODO(sjmiles): we should probably fallback to listening to script.loa
d |
| 58 throw 'core-shared-api: a %%callback%% parameter is required in the API
url'; |
| 59 } |
| 60 } |
| 61 // |
| 62 this.addScript(url); |
| 63 }; |
| 64 |
| 65 Loader.prototype = { |
| 66 |
| 67 callbackMacro: '%%callback%%', |
| 68 loaded: false, |
| 69 |
| 70 addScript: function(src) { |
| 71 var script = document.createElement('script'); |
| 72 script.src = src; |
| 73 script.onerror = this.error.bind(this); |
| 74 var s = document.querySelector('script'); |
| 75 s.parentNode.insertBefore(script, s); |
| 76 this.script = script; |
| 77 }, |
| 78 |
| 79 removeScript: function() { |
| 80 if (this.script.parentNode) { |
| 81 this.script.parentNode.removeChild(this.script); |
| 82 } |
| 83 this.script = null; |
| 84 }, |
| 85 |
| 86 error: function() { |
| 87 this.cleanup(); |
| 88 }, |
| 89 |
| 90 success: function() { |
| 91 this.loaded = true; |
| 92 this.cleanup(); |
| 93 this.result = Array.prototype.slice.call(arguments); |
| 94 this.instances.forEach(this.provide, this); |
| 95 this.instances = null; |
| 96 }, |
| 97 |
| 98 cleanup: function() { |
| 99 delete window[this.callbackName]; |
| 100 }, |
| 101 |
| 102 provide: function(instance) { |
| 103 instance.notify(instance, this.result); |
| 104 }, |
| 105 |
| 106 requestNotify: function(instance) { |
| 107 if (this.loaded) { |
| 108 this.provide(instance); |
| 109 } else { |
| 110 this.instances.push(instance); |
| 111 } |
| 112 } |
| 113 |
| 114 }; |
| 115 |
| 116 })(); |
OLD | NEW |