Depender.Client.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. // Licensed to Cloudera, Inc. under one
  2. // or more contributor license agreements. See the NOTICE file
  3. // distributed with this work for additional information
  4. // regarding copyright ownership. Cloudera, Inc. licenses this file
  5. // to you under the Apache License, Version 2.0 (the
  6. // "License"); you may not use this file except in compliance
  7. // with the License. You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. /*
  17. ---
  18. description: A dependency loader for the MooTools library that integrates with <a
  19. href="http://github.com/anutron/mootools-depender/tree/">the server side Depender
  20. library</a>.
  21. provides: [Depender.Client]
  22. requires: [Core/Class.Extras, Core/Element.Event]
  23. script: Depender.Client.js
  24. authors: [Aaron Newton]
  25. ...
  26. */
  27. var Depender = {
  28. options: {
  29. /*
  30. onRequire: $empty(options),
  31. onRequirementLoaded: $empty([scripts, options]),
  32. target: null,
  33. builder: '/depender/build.php'
  34. */
  35. },
  36. loadedSources: [],
  37. loaded: [],
  38. required: [],
  39. finished: [],
  40. lastLoaded: 0,
  41. require: function(options){
  42. if (!this.options.builder) return;
  43. this.fireEvent('require', options);
  44. var finish = function(script){
  45. this.finished.push(script);
  46. if (options.callback) {
  47. if (options.domready) window.addEvent('domready', options.callback.pass(options));
  48. else options.callback(options);
  49. }
  50. this.fireEvent('scriptLoaded', {
  51. script: this.loaded.join(', '),
  52. totalLoaded: (this.finished.length / this.required.length * 100).round(),
  53. currentLoaded: ((this.finished.length - this.lastLoaded) / (this.required.length - this.lastLoaded) * 100).round(),
  54. loaded: this.loaded
  55. });
  56. if (this.required.length == this.finished.length) this.lastLoaded = this.finished.length;
  57. this.fireEvent('requirementLoaded', [this.loaded, options]);
  58. }.bind(this);
  59. var src = [this.options.builder + '?client=true'];
  60. if (options.scripts) {
  61. var scripts = $splat(options.scripts).filter(function(script) {
  62. return !this.loaded.contains(script);
  63. }, this);
  64. if (scripts.length) src.push('require=' + scripts.join(','));
  65. }
  66. if (options.sources) {
  67. var sources = $splat(options.sources).filter(function(source){
  68. return !this.loadedSources.contains(source);
  69. }, this);
  70. if (sources.length) src.push('requireLibs=' + $splat(sources).join(','));
  71. }
  72. if (src.length == 1) {
  73. finish();
  74. return this;
  75. }
  76. if (this.loaded.length) {
  77. src.push('exclude=' + this.loaded.join(','));
  78. }
  79. var finished;
  80. var script = new Element('script', {
  81. src: src.join('&'),
  82. events: {
  83. //IE doesn't fire a load event for scripts, so we monitor the ready state
  84. readystatechange: function(){
  85. if (['loaded', 'complete'].contains(this.readyState) && !finished) {
  86. finished = true;
  87. finish(script);
  88. }
  89. },
  90. load: function(){
  91. if (!finished) {
  92. finished = true;
  93. finish(script);
  94. }
  95. }
  96. }
  97. }).inject(this.options.target || document.head);
  98. this.required.push(script);
  99. return this;
  100. }
  101. };
  102. //make it easy to switch between the server side and the client side versions of this library.
  103. ['enableLog', 'disableLog', 'include'].each(function(fn) {
  104. Depender[fn] = $lambda(Depender);
  105. });
  106. $extend(Depender, new Events);
  107. $extend(Depender, new Options);
  108. (function(){
  109. if (!Browser.Engine.trident) return;
  110. /*
  111. I am going to hell for this.
  112. Override Mootool's $ method and its Element.implement method for IE.
  113. Override $ to disable the caching elements whenever Element.implement is called.
  114. This hack exists because we load dependencies on the fly with Depender and IE does not
  115. expose the element prototype. Thus, if we extend an element (through $) once, and then
  116. subsequently implement new properties onto the Element prototype, we need to re-apply
  117. them to any element instances fetched with MooTools.
  118. Like I said, I'm going to hell for this.
  119. */
  120. var impl = Element.implement;
  121. //keep track of the "version" that the element has been implemented
  122. var version = 0;
  123. Element.implement = function() {
  124. version++;
  125. impl.apply(Element, arguments);
  126. };
  127. var old$ = document.id;
  128. document.id = (function(){
  129. return function(el, nocash, doc){
  130. el = old$(el, nocash, doc);
  131. //if the version of this element is behind the current
  132. //Element implementation, re-process it
  133. if (el && el.$version != version
  134. && el.$family
  135. //mootools doesn't extend window, document, whitespace, or textnode
  136. //in the same way as it does Element; we exclude them here
  137. && el.$family.name != 'window'
  138. && el.$family.name != 'document'
  139. && el.$family.name != 'whitespace'
  140. && el.$family.name != 'textnode') {
  141. el.$family = null;
  142. el = old$(el);
  143. el.$version = version;
  144. }
  145. return el;
  146. };
  147. })();
  148. })();