extjs-mvc 0.4.0.j → 0.4.0.k

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) hide show
  1. data/Rakefile +1 -1
  2. data/VERSION +1 -1
  3. data/lib/extjs-mvc.rb +0 -14
  4. data/lib/extjs-mvc/api.rb +14 -27
  5. data/lib/extjs-mvc/src/App.js +219 -0
  6. data/lib/extjs-mvc/src/MVC.js +260 -0
  7. data/lib/extjs-mvc/src/Presenter.js +52 -0
  8. data/lib/extjs-mvc/src/README.rdoc +69 -0
  9. data/lib/extjs-mvc/src/controller/Controller.js +278 -0
  10. data/lib/extjs-mvc/src/controller/CrudController.js +460 -0
  11. data/lib/extjs-mvc/src/lib/Array.js +26 -0
  12. data/lib/extjs-mvc/src/lib/Booter.js +417 -0
  13. data/lib/extjs-mvc/src/lib/ClassManager.js +191 -0
  14. data/lib/extjs-mvc/src/lib/ControllerClassManager.js +95 -0
  15. data/lib/extjs-mvc/src/lib/Dependencies.js +44 -0
  16. data/lib/extjs-mvc/src/lib/DispatchMatcher.js +98 -0
  17. data/lib/extjs-mvc/src/lib/Dispatcher.js +129 -0
  18. data/lib/extjs-mvc/src/lib/Environment.js +43 -0
  19. data/lib/extjs-mvc/src/lib/Inflector.js +155 -0
  20. data/lib/extjs-mvc/src/lib/ModelClassManager.js +19 -0
  21. data/lib/extjs-mvc/src/lib/Route.js +139 -0
  22. data/lib/extjs-mvc/src/lib/Router.js +282 -0
  23. data/lib/extjs-mvc/src/lib/String.js +94 -0
  24. data/lib/extjs-mvc/src/lib/ViewClassManager.js +229 -0
  25. data/lib/extjs-mvc/src/lib/notes.txt +32 -0
  26. data/lib/extjs-mvc/src/model/AdapterManager.js +30 -0
  27. data/lib/extjs-mvc/src/model/Association.js +26 -0
  28. data/lib/extjs-mvc/src/model/Base.js +63 -0
  29. data/lib/extjs-mvc/src/model/BelongsToAssociation.js +116 -0
  30. data/lib/extjs-mvc/src/model/Cache.js +131 -0
  31. data/lib/extjs-mvc/src/model/HasManyAssociation.js +160 -0
  32. data/lib/extjs-mvc/src/model/Model.js +331 -0
  33. data/lib/extjs-mvc/src/model/UrlBuilder.js +106 -0
  34. data/lib/extjs-mvc/src/model/adapters/AbstractAdapter.js +296 -0
  35. data/lib/extjs-mvc/src/model/adapters/MemoryAdapter.js +103 -0
  36. data/lib/extjs-mvc/src/model/adapters/RESTAdapter.js +345 -0
  37. data/lib/extjs-mvc/src/model/adapters/RESTJSONAdapter.js +68 -0
  38. data/lib/extjs-mvc/src/model/adapters/notes.txt +42 -0
  39. data/lib/extjs-mvc/src/model/associations/Association.js +192 -0
  40. data/lib/extjs-mvc/src/model/associations/notes.txt +87 -0
  41. data/lib/extjs-mvc/src/model/validations/Errors.js +136 -0
  42. data/lib/extjs-mvc/src/model/validations/Plugin.js +139 -0
  43. data/lib/extjs-mvc/src/model/validations/Validations.js +276 -0
  44. data/lib/extjs-mvc/src/notes/Charts.graffle +0 -0
  45. data/lib/extjs-mvc/src/overrides/Ext.Component.js +21 -0
  46. data/lib/extjs-mvc/src/overrides/Ext.extend.js +142 -0
  47. data/lib/extjs-mvc/src/spec/Array.spec.js +15 -0
  48. data/lib/extjs-mvc/src/spec/ExtMVC.spec.js +65 -0
  49. data/lib/extjs-mvc/src/spec/Model.spec.js +370 -0
  50. data/lib/extjs-mvc/src/spec/OS.spec.js +83 -0
  51. data/lib/extjs-mvc/src/spec/Router.spec.js +99 -0
  52. data/lib/extjs-mvc/src/spec/SpecHelper.js +106 -0
  53. data/lib/extjs-mvc/src/spec/String.spec.js +83 -0
  54. data/lib/extjs-mvc/src/spec/model/AbstractAdapter.spec.js +49 -0
  55. data/lib/extjs-mvc/src/spec/model/Associations.spec.js +99 -0
  56. data/lib/extjs-mvc/src/spec/model/Cache.spec.js +5 -0
  57. data/lib/extjs-mvc/src/spec/model/RESTAdapter.spec.js +19 -0
  58. data/lib/extjs-mvc/src/spec/model/ValidationErrors.spec.js +64 -0
  59. data/lib/extjs-mvc/src/spec/model/Validations.spec.js +166 -0
  60. data/lib/extjs-mvc/src/spec/model/ValidationsPlugin.spec.js +108 -0
  61. data/lib/extjs-mvc/src/spec/suite.html +60 -0
  62. data/lib/extjs-mvc/src/specs-old/JSSpec.css +216 -0
  63. data/lib/extjs-mvc/src/specs-old/JSSpec.js +1512 -0
  64. data/lib/extjs-mvc/src/specs-old/all.html +66 -0
  65. data/lib/extjs-mvc/src/specs-old/base.js +14 -0
  66. data/lib/extjs-mvc/src/specs-old/controller.js +17 -0
  67. data/lib/extjs-mvc/src/specs-old/diff_match_patch.js +1 -0
  68. data/lib/extjs-mvc/src/specs-old/model.js +70 -0
  69. data/lib/extjs-mvc/src/specs-old/route.js +38 -0
  70. data/lib/extjs-mvc/src/specs-old/router.js +59 -0
  71. data/lib/extjs-mvc/src/specs-old/string.js +22 -0
  72. data/lib/extjs-mvc/src/testrunner/JSpecFormatter.js +111 -0
  73. data/lib/extjs-mvc/src/testrunner/TestClient.js +181 -0
  74. data/lib/extjs-mvc/src/testrunner/TestGrid.js +351 -0
  75. data/lib/extjs-mvc/src/testrunner/TestRunner.js +110 -0
  76. data/lib/extjs-mvc/src/testrunner/TestViewport.js +94 -0
  77. data/lib/extjs-mvc/src/vendor.yml +30 -0
  78. data/lib/extjs-mvc/src/vendor/ext-3.1.1/vendor.yml +16 -0
  79. data/lib/extjs-mvc/src/view/FormWindow.js +184 -0
  80. data/lib/extjs-mvc/src/view/HasManyEditorGridPanel.js +211 -0
  81. data/lib/extjs-mvc/src/view/scaffold/Edit.js +46 -0
  82. data/lib/extjs-mvc/src/view/scaffold/Index.js +561 -0
  83. data/lib/extjs-mvc/src/view/scaffold/New.js +20 -0
  84. data/lib/extjs-mvc/src/view/scaffold/ScaffoldFormPanel.js +255 -0
  85. data/lib/{vendor.yml → extjs-mvc/vendor.yml} +0 -0
  86. data/test/app/vendor/extjs-mvc/App.js +219 -0
  87. data/test/app/vendor/extjs-mvc/MVC.js +260 -0
  88. data/test/app/vendor/extjs-mvc/Presenter.js +52 -0
  89. data/test/app/vendor/extjs-mvc/README.rdoc +69 -0
  90. data/test/app/vendor/extjs-mvc/controller/Controller.js +278 -0
  91. data/test/app/vendor/extjs-mvc/controller/CrudController.js +460 -0
  92. data/test/app/vendor/extjs-mvc/lib/Array.js +26 -0
  93. data/test/app/vendor/extjs-mvc/lib/Booter.js +417 -0
  94. data/test/app/vendor/extjs-mvc/lib/ClassManager.js +191 -0
  95. data/test/app/vendor/extjs-mvc/lib/ControllerClassManager.js +95 -0
  96. data/test/app/vendor/extjs-mvc/lib/Dependencies.js +44 -0
  97. data/test/app/vendor/extjs-mvc/lib/DispatchMatcher.js +98 -0
  98. data/test/app/vendor/extjs-mvc/lib/Dispatcher.js +129 -0
  99. data/test/app/vendor/extjs-mvc/lib/Environment.js +43 -0
  100. data/test/app/vendor/extjs-mvc/lib/Inflector.js +155 -0
  101. data/test/app/vendor/extjs-mvc/lib/ModelClassManager.js +19 -0
  102. data/test/app/vendor/extjs-mvc/lib/Route.js +139 -0
  103. data/test/app/vendor/extjs-mvc/lib/Router.js +282 -0
  104. data/test/app/vendor/extjs-mvc/lib/String.js +94 -0
  105. data/test/app/vendor/extjs-mvc/lib/ViewClassManager.js +229 -0
  106. data/test/app/vendor/extjs-mvc/lib/notes.txt +32 -0
  107. data/test/app/vendor/extjs-mvc/model/AdapterManager.js +30 -0
  108. data/test/app/vendor/extjs-mvc/model/Association.js +26 -0
  109. data/test/app/vendor/extjs-mvc/model/Base.js +63 -0
  110. data/test/app/vendor/extjs-mvc/model/BelongsToAssociation.js +116 -0
  111. data/test/app/vendor/extjs-mvc/model/Cache.js +131 -0
  112. data/test/app/vendor/extjs-mvc/model/HasManyAssociation.js +160 -0
  113. data/test/app/vendor/extjs-mvc/model/Model.js +331 -0
  114. data/test/app/vendor/extjs-mvc/model/UrlBuilder.js +106 -0
  115. data/test/app/vendor/extjs-mvc/model/adapters/AbstractAdapter.js +296 -0
  116. data/test/app/vendor/extjs-mvc/model/adapters/MemoryAdapter.js +103 -0
  117. data/test/app/vendor/extjs-mvc/model/adapters/RESTAdapter.js +345 -0
  118. data/test/app/vendor/extjs-mvc/model/adapters/RESTJSONAdapter.js +68 -0
  119. data/test/app/vendor/extjs-mvc/model/adapters/notes.txt +42 -0
  120. data/test/app/vendor/extjs-mvc/model/associations/Association.js +192 -0
  121. data/test/app/vendor/extjs-mvc/model/associations/notes.txt +87 -0
  122. data/test/app/vendor/extjs-mvc/model/validations/Errors.js +136 -0
  123. data/test/app/vendor/extjs-mvc/model/validations/Plugin.js +139 -0
  124. data/test/app/vendor/extjs-mvc/model/validations/Validations.js +276 -0
  125. data/test/app/vendor/extjs-mvc/notes/Charts.graffle +0 -0
  126. data/test/app/vendor/extjs-mvc/overrides/Ext.Component.js +21 -0
  127. data/test/app/vendor/extjs-mvc/overrides/Ext.extend.js +142 -0
  128. data/test/app/vendor/extjs-mvc/spec/Array.spec.js +15 -0
  129. data/test/app/vendor/extjs-mvc/spec/ExtMVC.spec.js +65 -0
  130. data/test/app/vendor/extjs-mvc/spec/Model.spec.js +370 -0
  131. data/test/app/vendor/extjs-mvc/spec/OS.spec.js +83 -0
  132. data/test/app/vendor/extjs-mvc/spec/Router.spec.js +99 -0
  133. data/test/app/vendor/extjs-mvc/spec/SpecHelper.js +106 -0
  134. data/test/app/vendor/extjs-mvc/spec/String.spec.js +83 -0
  135. data/test/app/vendor/extjs-mvc/spec/model/AbstractAdapter.spec.js +49 -0
  136. data/test/app/vendor/extjs-mvc/spec/model/Associations.spec.js +99 -0
  137. data/test/app/vendor/extjs-mvc/spec/model/Cache.spec.js +5 -0
  138. data/test/app/vendor/extjs-mvc/spec/model/RESTAdapter.spec.js +19 -0
  139. data/test/app/vendor/extjs-mvc/spec/model/ValidationErrors.spec.js +64 -0
  140. data/test/app/vendor/extjs-mvc/spec/model/Validations.spec.js +166 -0
  141. data/test/app/vendor/extjs-mvc/spec/model/ValidationsPlugin.spec.js +108 -0
  142. data/test/app/vendor/extjs-mvc/spec/suite.html +60 -0
  143. data/test/app/vendor/extjs-mvc/specs-old/JSSpec.css +216 -0
  144. data/test/app/vendor/extjs-mvc/specs-old/JSSpec.js +1512 -0
  145. data/test/app/vendor/extjs-mvc/specs-old/all.html +66 -0
  146. data/test/app/vendor/extjs-mvc/specs-old/base.js +14 -0
  147. data/test/app/vendor/extjs-mvc/specs-old/controller.js +17 -0
  148. data/test/app/vendor/extjs-mvc/specs-old/diff_match_patch.js +1 -0
  149. data/test/app/vendor/extjs-mvc/specs-old/model.js +70 -0
  150. data/test/app/vendor/extjs-mvc/specs-old/route.js +38 -0
  151. data/test/app/vendor/extjs-mvc/specs-old/router.js +59 -0
  152. data/test/app/vendor/extjs-mvc/specs-old/string.js +22 -0
  153. data/test/app/vendor/extjs-mvc/testrunner/JSpecFormatter.js +111 -0
  154. data/test/app/vendor/extjs-mvc/testrunner/TestClient.js +181 -0
  155. data/test/app/vendor/extjs-mvc/testrunner/TestGrid.js +351 -0
  156. data/test/app/vendor/extjs-mvc/testrunner/TestRunner.js +110 -0
  157. data/test/app/vendor/extjs-mvc/testrunner/TestViewport.js +94 -0
  158. data/test/app/vendor/extjs-mvc/vendor.yml +30 -0
  159. data/test/app/vendor/extjs-mvc/vendor/ext-3.1.1/vendor.yml +16 -0
  160. data/test/app/vendor/extjs-mvc/view/FormWindow.js +184 -0
  161. data/test/app/vendor/extjs-mvc/view/HasManyEditorGridPanel.js +211 -0
  162. data/test/app/vendor/extjs-mvc/view/scaffold/Edit.js +46 -0
  163. data/test/app/vendor/extjs-mvc/view/scaffold/Index.js +561 -0
  164. data/test/app/vendor/extjs-mvc/view/scaffold/New.js +20 -0
  165. data/test/app/vendor/extjs-mvc/view/scaffold/ScaffoldFormPanel.js +255 -0
  166. data/test/helper.rb +7 -1
  167. data/test/test_extjs-mvc.rb +46 -0
  168. metadata +167 -7
  169. data/test/test_extjs-mvc-gem.rb +0 -7
@@ -0,0 +1,66 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ko">
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
5
+ <title>JSSpec results</title>
6
+ <link rel="stylesheet" type="text/css" href="JSSpec.css" />
7
+ <script src="diff_match_patch.js" type="text/javascript"></script>
8
+ <script src="JSSpec.js" type="text/javascript"></script>
9
+ <script src="../../ext/adapter/ext/ext-base.js" type="text/javascript" charset="utf-8"></script>
10
+ <script src="../../ext/ext-all.js" type="text/javascript" charset="utf-8"></script>
11
+ <script src="../base.js" type="text/javascript" charset="utf-8"></script>
12
+ <script src="../lib/application.js" type="text/javascript" charset="utf-8"></script>
13
+ <script src="../model/base.js" type="text/javascript" charset="utf-8"></script>
14
+ <script src="../controller/base.js" type="text/javascript" charset="utf-8"></script>
15
+ <script src="../controller/crud_controller.js" type="text/javascript" charset="utf-8"></script>
16
+ <script src="../lib/router.js" type="text/javascript" charset="utf-8"></script>
17
+ <script src="../lib/route.js" type="text/javascript" charset="utf-8"></script>
18
+ <script src="../lib/flash.js" type="text/javascript" charset="utf-8"></script>
19
+ <script src="../lib/string_methods.js" type="text/javascript" charset="utf-8"></script>
20
+ <script src="../lib/request_exception_handler.js" type="text/javascript" charset="utf-8"></script>
21
+
22
+ <script src="base.js" type="text/javascript" charset="utf-8"></script>
23
+ <script src="router.js" type="text/javascript" charset="utf-8"></script>
24
+ <script src="route.js" type="text/javascript" charset="utf-8"></script>
25
+ <script type="text/javascript">// <![CDATA[
26
+ // Define a new model and test that the various methods work correctly
27
+ AgentPageTemplate = new ExtMVC.model.Base('agent_page_template', {
28
+ fields: [{name: 'id', type: 'int'}]
29
+ });
30
+
31
+ // mock some views
32
+ AgentPageTemplateIndexPanel = {};
33
+ AgentPageTemplateEditPanel = {};
34
+ AgentPageTemplateNewPanel = {};
35
+
36
+ // stub out a layout manager
37
+ ExtMVC.LayoutManager.LeftMenuLayoutManager = function() {
38
+ this.initialize = function() {
39
+ return true;
40
+ }
41
+ };
42
+
43
+ application = new Application();
44
+
45
+ // set up a corresponding controller for the model above
46
+ AgentPageTemplatesController = Ext.extend(ExtMVC.controller.CrudController, {
47
+ constructor: function(config) {
48
+ AgentPageTemplatesController.superclass.constructor.call(this, {
49
+ model : AgentPageTemplate,
50
+ indexPanel : AgentPageTemplateIndexPanel,
51
+ editPanel : AgentPageTemplateEditPanel,
52
+ newPanel : AgentPageTemplateNewPanel
53
+ });
54
+ }
55
+ });
56
+
57
+ var controller = new AgentPageTemplatesController();
58
+
59
+ // ]]></script>
60
+
61
+ <script src="model.js" type="text/javascript" charset="utf-8"></script>
62
+ <script src="controller.js" type="text/javascript" charset="utf-8"></script>
63
+ <script src="string.js" type="text/javascript" charset="utf-8"></script>
64
+ </head>
65
+ <body><div style="display:none;"><p>A</p><p>B</p></div></body>
66
+ </html>
@@ -0,0 +1,14 @@
1
+ describe('ExtMVC.behaveLikeRails()', {
2
+ before_each: function() {
3
+ params_mock = {key: 'value'};
4
+ ExtMVC.params = params_mock;
5
+ },
6
+ 'should make params a global variable': function() {
7
+ // this ought to work but doesn't (at least on FF3)
8
+ // value_of(params).should_be_undefined();
9
+
10
+ value_of(typeof(params)).should_be('undefined');
11
+ ExtMVC.behaveLikeRails();
12
+ value_of(params).should_be(params_mock);
13
+ }
14
+ });
@@ -0,0 +1,17 @@
1
+ describe('An example controller', {
2
+ 'maintain a reference to the application': function() {
3
+ value_of(controller.application).should_be(application);
4
+ },
5
+ 'maintain a reference to the model': function() {
6
+ value_of(controller.model).should_be(AgentPageTemplate)
7
+ },
8
+ 'return the correct batch destroy url': function() {
9
+ value_of(controller.batchDestroyUrl).should_be('/admin/batch_destroy_agent_page_templates.ext_json')
10
+ },
11
+ 'return the correct delete confirmation message when deleting 1 item': function() {
12
+ value_of(controller.deleteMessage(1)).should_be('Are you sure you want to delete this Agent Page Template? This cannot be undone')
13
+ },
14
+ 'return the correct delete confirmation message when deleting more than one 1 item': function() {
15
+ value_of(controller.deleteMessage(2)).should_be('Are you sure you want to delete these Agent Page Templates? This cannot be undone')
16
+ }
17
+ });
@@ -0,0 +1 @@
1
+ function diff_match_patch(){this.Diff_Timeout=1.0;this.Diff_EditCost=4;this.Diff_DualThreshold=32;this.Match_Balance=0.5;this.Match_Threshold=0.5;this.Match_MinLength=100;this.Match_MaxLength=1000;this.Patch_Margin=4;function getMaxBits(){var maxbits=0;var oldi=1;var newi=2;while(oldi!=newi){maxbits++;oldi=newi;newi=newi<<1}return maxbits}this.Match_MaxBits=getMaxBits()}var DIFF_DELETE=-1;var DIFF_INSERT=1;var DIFF_EQUAL=0;diff_match_patch.prototype.diff_main=function(text1,text2,opt_checklines){if(text1==text2){return[[DIFF_EQUAL,text1]]}if(typeof opt_checklines=='undefined'){opt_checklines=true}var checklines=opt_checklines;var commonlength=this.diff_commonPrefix(text1,text2);var commonprefix=text1.substring(0,commonlength);text1=text1.substring(commonlength);text2=text2.substring(commonlength);commonlength=this.diff_commonSuffix(text1,text2);var commonsuffix=text1.substring(text1.length-commonlength);text1=text1.substring(0,text1.length-commonlength);text2=text2.substring(0,text2.length-commonlength);var diffs=this.diff_compute(text1,text2,checklines);if(commonprefix){diffs.unshift([DIFF_EQUAL,commonprefix])}if(commonsuffix){diffs.push([DIFF_EQUAL,commonsuffix])}this.diff_cleanupMerge(diffs);return diffs};diff_match_patch.prototype.diff_compute=function(text1,text2,checklines){var diffs;if(!text1){return[[DIFF_INSERT,text2]]}if(!text2){return[[DIFF_DELETE,text1]]}var longtext=text1.length>text2.length?text1:text2;var shorttext=text1.length>text2.length?text2:text1;var i=longtext.indexOf(shorttext);if(i!=-1){diffs=[[DIFF_INSERT,longtext.substring(0,i)],[DIFF_EQUAL,shorttext],[DIFF_INSERT,longtext.substring(i+shorttext.length)]];if(text1.length>text2.length){diffs[0][0]=diffs[2][0]=DIFF_DELETE}return diffs}longtext=shorttext=null;var hm=this.diff_halfMatch(text1,text2);if(hm){var text1_a=hm[0];var text1_b=hm[1];var text2_a=hm[2];var text2_b=hm[3];var mid_common=hm[4];var diffs_a=this.diff_main(text1_a,text2_a,checklines);var diffs_b=this.diff_main(text1_b,text2_b,checklines);return diffs_a.concat([[DIFF_EQUAL,mid_common]],diffs_b)}if(checklines&&text1.length+text2.length<250){checklines=false}var linearray;if(checklines){var a=this.diff_linesToChars(text1,text2);text1=a[0];text2=a[1];linearray=a[2]}diffs=this.diff_map(text1,text2);if(!diffs){diffs=[[DIFF_DELETE,text1],[DIFF_INSERT,text2]]}if(checklines){this.diff_charsToLines(diffs,linearray);this.diff_cleanupSemantic(diffs);diffs.push([DIFF_EQUAL,'']);var pointer=0;var count_delete=0;var count_insert=0;var text_delete='';var text_insert='';while(pointer<diffs.length){if(diffs[pointer][0]==DIFF_INSERT){count_insert++;text_insert+=diffs[pointer][1]}else if(diffs[pointer][0]==DIFF_DELETE){count_delete++;text_delete+=diffs[pointer][1]}else{if(count_delete>=1&&count_insert>=1){var a=this.diff_main(text_delete,text_insert,false);diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert);pointer=pointer-count_delete-count_insert;for(var j=a.length-1;j>=0;j--){diffs.splice(pointer,0,a[j])}pointer=pointer+a.length}count_insert=0;count_delete=0;text_delete='';text_insert=''}pointer++}diffs.pop()}return diffs};diff_match_patch.prototype.diff_linesToChars=function(text1,text2){var linearray=[];var linehash={};linearray.push('');function diff_linesToCharsMunge(text){var chars='';while(text){var i=text.indexOf('\n');if(i==-1){i=text.length}var line=text.substring(0,i+1);text=text.substring(i+1);if(linehash.hasOwnProperty?linehash.hasOwnProperty(line):(linehash[line]!==undefined)){chars+=String.fromCharCode(linehash[line])}else{linearray.push(line);linehash[line]=linearray.length-1;chars+=String.fromCharCode(linearray.length-1)}}return chars}var chars1=diff_linesToCharsMunge(text1);var chars2=diff_linesToCharsMunge(text2);return[chars1,chars2,linearray]};diff_match_patch.prototype.diff_charsToLines=function(diffs,linearray){for(var x=0;x<diffs.length;x++){var chars=diffs[x][1];var text=[];for(var y=0;y<chars.length;y++){text.push(linearray[chars.charCodeAt(y)])}diffs[x][1]=text.join('')}};diff_match_patch.prototype.diff_map=function(text1,text2){var ms_end=(new Date()).getTime()+this.Diff_Timeout*1000;var max_d=text1.length+text2.length-1;var doubleEnd=this.Diff_DualThreshold*2<max_d;var v_map1=[];var v_map2=[];var v1={};var v2={};v1[1]=0;v2[1]=0;var x,y;var footstep;var footsteps={};var done=false;var hasOwnProperty=!!(footsteps.hasOwnProperty);var front=(text1.length+text2.length)%2;for(var d=0;d<max_d;d++){if(this.Diff_Timeout>0&&(new Date()).getTime()>ms_end){return null}v_map1[d]={};for(var k=-d;k<=d;k+=2){if(k==-d||k!=d&&v1[k-1]<v1[k+1]){x=v1[k+1]}else{x=v1[k-1]+1}y=x-k;if(doubleEnd){footstep=x+','+y;if(front&&(hasOwnProperty?footsteps.hasOwnProperty(footstep):(footsteps[footstep]!==undefined))){done=true}if(!front){footsteps[footstep]=d}}while(!done&&x<text1.length&&y<text2.length&&text1.charAt(x)==text2.charAt(y)){x++;y++;if(doubleEnd){footstep=x+','+y;if(front&&(hasOwnProperty?footsteps.hasOwnProperty(footstep):(footsteps[footstep]!==undefined))){done=true}if(!front){footsteps[footstep]=d}}}v1[k]=x;v_map1[d][x+','+y]=true;if(x==text1.length&&y==text2.length){return this.diff_path1(v_map1,text1,text2)}else if(done){v_map2=v_map2.slice(0,footsteps[footstep]+1);var a=this.diff_path1(v_map1,text1.substring(0,x),text2.substring(0,y));return a.concat(this.diff_path2(v_map2,text1.substring(x),text2.substring(y)))}}if(doubleEnd){v_map2[d]={};for(var k=-d;k<=d;k+=2){if(k==-d||k!=d&&v2[k-1]<v2[k+1]){x=v2[k+1]}else{x=v2[k-1]+1}y=x-k;footstep=(text1.length-x)+','+(text2.length-y);if(!front&&(hasOwnProperty?footsteps.hasOwnProperty(footstep):(footsteps[footstep]!==undefined))){done=true}if(front){footsteps[footstep]=d}while(!done&&x<text1.length&&y<text2.length&&text1.charAt(text1.length-x-1)==text2.charAt(text2.length-y-1)){x++;y++;footstep=(text1.length-x)+','+(text2.length-y);if(!front&&(hasOwnProperty?footsteps.hasOwnProperty(footstep):(footsteps[footstep]!==undefined))){done=true}if(front){footsteps[footstep]=d}}v2[k]=x;v_map2[d][x+','+y]=true;if(done){v_map1=v_map1.slice(0,footsteps[footstep]+1);var a=this.diff_path1(v_map1,text1.substring(0,text1.length-x),text2.substring(0,text2.length-y));return a.concat(this.diff_path2(v_map2,text1.substring(text1.length-x),text2.substring(text2.length-y)))}}}}return null};diff_match_patch.prototype.diff_path1=function(v_map,text1,text2){var path=[];var x=text1.length;var y=text2.length;var last_op=null;for(var d=v_map.length-2;d>=0;d--){while(1){if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty((x-1)+','+y):(v_map[d][(x-1)+','+y]!==undefined)){x--;if(last_op===DIFF_DELETE){path[0][1]=text1.charAt(x)+path[0][1]}else{path.unshift([DIFF_DELETE,text1.charAt(x)])}last_op=DIFF_DELETE;break}else if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty(x+','+(y-1)):(v_map[d][x+','+(y-1)]!==undefined)){y--;if(last_op===DIFF_INSERT){path[0][1]=text2.charAt(y)+path[0][1]}else{path.unshift([DIFF_INSERT,text2.charAt(y)])}last_op=DIFF_INSERT;break}else{x--;y--;if(last_op===DIFF_EQUAL){path[0][1]=text1.charAt(x)+path[0][1]}else{path.unshift([DIFF_EQUAL,text1.charAt(x)])}last_op=DIFF_EQUAL}}}return path};diff_match_patch.prototype.diff_path2=function(v_map,text1,text2){var path=[];var x=text1.length;var y=text2.length;var last_op=null;for(var d=v_map.length-2;d>=0;d--){while(1){if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty((x-1)+','+y):(v_map[d][(x-1)+','+y]!==undefined)){x--;if(last_op===DIFF_DELETE){path[path.length-1][1]+=text1.charAt(text1.length-x-1)}else{path.push([DIFF_DELETE,text1.charAt(text1.length-x-1)])}last_op=DIFF_DELETE;break}else if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty(x+','+(y-1)):(v_map[d][x+','+(y-1)]!==undefined)){y--;if(last_op===DIFF_INSERT){path[path.length-1][1]+=text2.charAt(text2.length-y-1)}else{path.push([DIFF_INSERT,text2.charAt(text2.length-y-1)])}last_op=DIFF_INSERT;break}else{x--;y--;if(last_op===DIFF_EQUAL){path[path.length-1][1]+=text1.charAt(text1.length-x-1)}else{path.push([DIFF_EQUAL,text1.charAt(text1.length-x-1)])}last_op=DIFF_EQUAL}}}return path};diff_match_patch.prototype.diff_commonPrefix=function(text1,text2){if(!text1||!text2||text1.charCodeAt(0)!==text2.charCodeAt(0)){return 0}var pointermin=0;var pointermax=Math.min(text1.length,text2.length);var pointermid=pointermax;var pointerstart=0;while(pointermin<pointermid){if(text1.substring(pointerstart,pointermid)==text2.substring(pointerstart,pointermid)){pointermin=pointermid;pointerstart=pointermin}else{pointermax=pointermid}pointermid=Math.floor((pointermax-pointermin)/2+pointermin)}return pointermid};diff_match_patch.prototype.diff_commonSuffix=function(text1,text2){if(!text1||!text2||text1.charCodeAt(text1.length-1)!==text2.charCodeAt(text2.length-1)){return 0}var pointermin=0;var pointermax=Math.min(text1.length,text2.length);var pointermid=pointermax;var pointerend=0;while(pointermin<pointermid){if(text1.substring(text1.length-pointermid,text1.length-pointerend)==text2.substring(text2.length-pointermid,text2.length-pointerend)){pointermin=pointermid;pointerend=pointermin}else{pointermax=pointermid}pointermid=Math.floor((pointermax-pointermin)/2+pointermin)}return pointermid};diff_match_patch.prototype.diff_halfMatch=function(text1,text2){var longtext=text1.length>text2.length?text1:text2;var shorttext=text1.length>text2.length?text2:text1;if(longtext.length<10||shorttext.length<1){return null}var dmp=this;function diff_halfMatchI(longtext,shorttext,i){var seed=longtext.substring(i,i+Math.floor(longtext.length/4));var j=-1;var best_common='';var best_longtext_a,best_longtext_b,best_shorttext_a,best_shorttext_b;while((j=shorttext.indexOf(seed,j+1))!=-1){var prefixLength=dmp.diff_commonPrefix(longtext.substring(i),shorttext.substring(j));var suffixLength=dmp.diff_commonSuffix(longtext.substring(0,i),shorttext.substring(0,j));if(best_common.length<suffixLength+prefixLength){best_common=shorttext.substring(j-suffixLength,j)+shorttext.substring(j,j+prefixLength);best_longtext_a=longtext.substring(0,i-suffixLength);best_longtext_b=longtext.substring(i+prefixLength);best_shorttext_a=shorttext.substring(0,j-suffixLength);best_shorttext_b=shorttext.substring(j+prefixLength)}}if(best_common.length>=longtext.length/2){return[best_longtext_a,best_longtext_b,best_shorttext_a,best_shorttext_b,best_common]}else{return null}}var hm1=diff_halfMatchI(longtext,shorttext,Math.ceil(longtext.length/4));var hm2=diff_halfMatchI(longtext,shorttext,Math.ceil(longtext.length/2));var hm;if(!hm1&&!hm2){return null}else if(!hm2){hm=hm1}else if(!hm1){hm=hm2}else{hm=hm1[4].length>hm2[4].length?hm1:hm2}var text1_a,text1_b,text2_a,text2_b;if(text1.length>text2.length){text1_a=hm[0];text1_b=hm[1];text2_a=hm[2];text2_b=hm[3]}else{text2_a=hm[0];text2_b=hm[1];text1_a=hm[2];text1_b=hm[3]}var mid_common=hm[4];return[text1_a,text1_b,text2_a,text2_b,mid_common]};diff_match_patch.prototype.diff_cleanupSemantic=function(diffs){var changes=false;var equalities=[];var lastequality=null;var pointer=0;var length_changes1=0;var length_changes2=0;while(pointer<diffs.length){if(diffs[pointer][0]==DIFF_EQUAL){equalities.push(pointer);length_changes1=length_changes2;length_changes2=0;lastequality=diffs[pointer][1]}else{length_changes2+=diffs[pointer][1].length;if(lastequality!==null&&(lastequality.length<=length_changes1)&&(lastequality.length<=length_changes2)){diffs.splice(equalities[equalities.length-1],0,[DIFF_DELETE,lastequality]);diffs[equalities[equalities.length-1]+1][0]=DIFF_INSERT;equalities.pop();equalities.pop();pointer=equalities.length?equalities[equalities.length-1]:-1;length_changes1=0;length_changes2=0;lastequality=null;changes=true}}pointer++}if(changes){this.diff_cleanupMerge(diffs)}this.diff_cleanupSemanticLossless(diffs)};diff_match_patch.prototype.diff_cleanupSemanticLossless=function(diffs){function diff_cleanupSemanticScore(one,two,three){var whitespace=/\s/;var score=0;if(one.charAt(one.length-1).match(whitespace)||two.charAt(0).match(whitespace)){score++}if(two.charAt(two.length-1).match(whitespace)||three.charAt(0).match(whitespace)){score++}return score}var pointer=1;while(pointer<diffs.length-1){if(diffs[pointer-1][0]==DIFF_EQUAL&&diffs[pointer+1][0]==DIFF_EQUAL){var equality1=diffs[pointer-1][1];var edit=diffs[pointer][1];var equality2=diffs[pointer+1][1];var commonOffset=this.diff_commonSuffix(equality1,edit);if(commonOffset){var commonString=edit.substring(edit.length-commonOffset);equality1=equality1.substring(0,equality1.length-commonOffset);edit=commonString+edit.substring(0,edit.length-commonOffset);equality2=commonString+equality2}var bestEquality1=equality1;var bestEdit=edit;var bestEquality2=equality2;var bestScore=diff_cleanupSemanticScore(equality1,edit,equality2);while(edit.charAt(0)===equality2.charAt(0)){equality1+=edit.charAt(0);edit=edit.substring(1)+equality2.charAt(0);equality2=equality2.substring(1);var score=diff_cleanupSemanticScore(equality1,edit,equality2);if(score>=bestScore){bestScore=score;bestEquality1=equality1;bestEdit=edit;bestEquality2=equality2}}if(diffs[pointer-1][1]!=bestEquality1){diffs[pointer-1][1]=bestEquality1;diffs[pointer][1]=bestEdit;diffs[pointer+1][1]=bestEquality2}}pointer++}};diff_match_patch.prototype.diff_cleanupEfficiency=function(diffs){var changes=false;var equalities=[];var lastequality='';var pointer=0;var pre_ins=false;var pre_del=false;var post_ins=false;var post_del=false;while(pointer<diffs.length){if(diffs[pointer][0]==DIFF_EQUAL){if(diffs[pointer][1].length<this.Diff_EditCost&&(post_ins||post_del)){equalities.push(pointer);pre_ins=post_ins;pre_del=post_del;lastequality=diffs[pointer][1]}else{equalities=[];lastequality=''}post_ins=post_del=false}else{if(diffs[pointer][0]==DIFF_DELETE){post_del=true}else{post_ins=true}if(lastequality&&((pre_ins&&pre_del&&post_ins&&post_del)||((lastequality.length<this.Diff_EditCost/2)&&(pre_ins+pre_del+post_ins+post_del)==3))){diffs.splice(equalities[equalities.length-1],0,[DIFF_DELETE,lastequality]);diffs[equalities[equalities.length-1]+1][0]=DIFF_INSERT;equalities.pop();lastequality='';if(pre_ins&&pre_del){post_ins=post_del=true;equalities=[]}else{equalities.pop();pointer=equalities.length?equalities[equalities.length-1]:-1;post_ins=post_del=false}changes=true}}pointer++}if(changes){this.diff_cleanupMerge(diffs)}};diff_match_patch.prototype.diff_cleanupMerge=function(diffs){diffs.push([DIFF_EQUAL,'']);var pointer=0;var count_delete=0;var count_insert=0;var text_delete='';var text_insert='';var commonlength;while(pointer<diffs.length){if(diffs[pointer][0]==DIFF_INSERT){count_insert++;text_insert+=diffs[pointer][1];pointer++}else if(diffs[pointer][0]==DIFF_DELETE){count_delete++;text_delete+=diffs[pointer][1];pointer++}else{if(count_delete!==0||count_insert!==0){if(count_delete!==0&&count_insert!==0){commonlength=this.diff_commonPrefix(text_insert,text_delete);if(commonlength!==0){if((pointer-count_delete-count_insert)>0&&diffs[pointer-count_delete-count_insert-1][0]==DIFF_EQUAL){diffs[pointer-count_delete-count_insert-1][1]+=text_insert.substring(0,commonlength)}else{diffs.splice(0,0,[DIFF_EQUAL,text_insert.substring(0,commonlength)]);pointer++}text_insert=text_insert.substring(commonlength);text_delete=text_delete.substring(commonlength)}commonlength=this.diff_commonSuffix(text_insert,text_delete);if(commonlength!==0){diffs[pointer][1]=text_insert.substring(text_insert.length-commonlength)+diffs[pointer][1];text_insert=text_insert.substring(0,text_insert.length-commonlength);text_delete=text_delete.substring(0,text_delete.length-commonlength)}}if(count_delete===0){diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert,[DIFF_INSERT,text_insert])}else if(count_insert===0){diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert,[DIFF_DELETE,text_delete])}else{diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert,[DIFF_DELETE,text_delete],[DIFF_INSERT,text_insert])}pointer=pointer-count_delete-count_insert+(count_delete?1:0)+(count_insert?1:0)+1}else if(pointer!==0&&diffs[pointer-1][0]==DIFF_EQUAL){diffs[pointer-1][1]+=diffs[pointer][1];diffs.splice(pointer,1)}else{pointer++}count_insert=0;count_delete=0;text_delete='';text_insert=''}}if(diffs[diffs.length-1][1]===''){diffs.pop()}var changes=false;pointer=1;while(pointer<diffs.length-1){if(diffs[pointer-1][0]==DIFF_EQUAL&&diffs[pointer+1][0]==DIFF_EQUAL){if(diffs[pointer][1].substring(diffs[pointer][1].length-diffs[pointer-1][1].length)==diffs[pointer-1][1]){diffs[pointer][1]=diffs[pointer-1][1]+diffs[pointer][1].substring(0,diffs[pointer][1].length-diffs[pointer-1][1].length);diffs[pointer+1][1]=diffs[pointer-1][1]+diffs[pointer+1][1];diffs.splice(pointer-1,1);changes=true}else if(diffs[pointer][1].substring(0,diffs[pointer+1][1].length)==diffs[pointer+1][1]){diffs[pointer-1][1]+=diffs[pointer+1][1];diffs[pointer][1]=diffs[pointer][1].substring(diffs[pointer+1][1].length)+diffs[pointer+1][1];diffs.splice(pointer+1,1);changes=true}}pointer++}if(changes){this.diff_cleanupMerge(diffs)}};diff_match_patch.prototype.diff_addIndex=function(diffs){var i=0;for(var x=0;x<diffs.length;x++){diffs[x].push(i);if(diffs[x][0]!==DIFF_DELETE){i+=diffs[x][1].length}}};diff_match_patch.prototype.diff_xIndex=function(diffs,loc){var chars1=0;var chars2=0;var last_chars1=0;var last_chars2=0;var x;for(x=0;x<diffs.length;x++){if(diffs[x][0]!==DIFF_INSERT){chars1+=diffs[x][1].length}if(diffs[x][0]!==DIFF_DELETE){chars2+=diffs[x][1].length}if(chars1>loc){break}last_chars1=chars1;last_chars2=chars2}if(diffs.length!=x&&diffs[x][0]===DIFF_DELETE){return last_chars2}return last_chars2+(loc-last_chars1)};diff_match_patch.prototype.diff_prettyHtml=function(diffs){this.diff_addIndex(diffs);var html=[];for(var x=0;x<diffs.length;x++){var m=diffs[x][0];var t=diffs[x][1];var i=diffs[x][2];t=t.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');t=t.replace(/\n/g,'&para;<BR>');if(m===DIFF_DELETE){html.push('<DEL STYLE="background:#FFE6E6;" TITLE="i=',i,'">',t,'</DEL>')}else if(m===DIFF_INSERT){html.push('<INS STYLE="background:#E6FFE6;" TITLE="i=',i,'">',t,'</INS>')}else{html.push('<SPAN TITLE="i=',i,'">',t,'</SPAN>')}}return html.join('')};diff_match_patch.prototype.diff_text1=function(diffs){var txt=[];for(var x=0;x<diffs.length;x++){if(diffs[x][0]!==DIFF_INSERT){txt.push(diffs[x][1])}}return txt.join('')};diff_match_patch.prototype.diff_text2=function(diffs){var txt=[];for(var x=0;x<diffs.length;x++){if(diffs[x][0]!==DIFF_DELETE){txt.push(diffs[x][1])}}return txt.join('')};diff_match_patch.prototype.diff_toDelta=function(diffs){var txt=[];for(var x=0;x<diffs.length;x++){switch(diffs[x][0]){case DIFF_DELETE:txt.push('-',diffs[x][1].length,'\t');break;case DIFF_EQUAL:txt.push('=',diffs[x][1].length,'\t');break;case DIFF_INSERT:txt.push('+',encodeURI(diffs[x][1]),'\t');break;default:alert('Invalid diff operation in diff_toDelta()')}}return txt.join('').replace(/%20/g,' ')};diff_match_patch.prototype.diff_fromDelta=function(text1,delta){var diffs=[];var pointer=0;var tokens=delta.split(/\t/g);for(var x=0;x<tokens.length;x++){var param=tokens[x].substring(1);switch(tokens[x].charAt(0)){case'-':case'=':var n=parseInt(param,10);if(isNaN(n)||n<0){alert('Invalid number in diff_fromDelta()')}else{var text=text1.substring(pointer,pointer+=n);if(tokens[x].charAt(0)=='='){diffs.push([DIFF_EQUAL,text])}else{diffs.push([DIFF_DELETE,text])}}break;case'+':diffs.push([DIFF_INSERT,decodeURI(param)]);break;default:if(tokens[x]){alert('Invalid diff operation in diff_fromDelta()')}}}if(pointer!=text1.length){alert('Text length mismatch in diff_fromDelta()')}return diffs};diff_match_patch.prototype.match_main=function(text,pattern,loc){loc=Math.max(0,Math.min(loc,text.length-pattern.length));if(text==pattern){return 0}else if(text.length===0){return null}else if(text.substring(loc,loc+pattern.length)==pattern){return loc}else{return this.match_bitap(text,pattern,loc)}};diff_match_patch.prototype.match_bitap=function(text,pattern,loc){if(pattern.length>this.Match_MaxBits){return alert('Pattern too long for this browser.')}var s=this.match_alphabet(pattern);var score_text_length=text.length;score_text_length=Math.max(score_text_length,this.Match_MinLength);score_text_length=Math.min(score_text_length,this.Match_MaxLength);var dmp=this;function match_bitapScore(e,x){var d=Math.abs(loc-x);return(e/pattern.length/dmp.Match_Balance)+(d/score_text_length/(1.0-dmp.Match_Balance))}var score_threshold=this.Match_Threshold;var best_loc=text.indexOf(pattern,loc);if(best_loc!=-1){score_threshold=Math.min(match_bitapScore(0,best_loc),score_threshold)}best_loc=text.lastIndexOf(pattern,loc+pattern.length);if(best_loc!=-1){score_threshold=Math.min(match_bitapScore(0,best_loc),score_threshold)}var matchmask=1<<(pattern.length-1);best_loc=null;var bin_min,bin_mid;var bin_max=Math.max(loc+loc,text.length);var last_rd;for(var d=0;d<pattern.length;d++){var rd=Array(text.length);bin_min=loc;bin_mid=bin_max;while(bin_min<bin_mid){if(match_bitapScore(d,bin_mid)<score_threshold){bin_min=bin_mid}else{bin_max=bin_mid}bin_mid=Math.floor((bin_max-bin_min)/2+bin_min)}bin_max=bin_mid;var start=Math.max(0,loc-(bin_mid-loc)-1);var finish=Math.min(text.length-1,pattern.length+bin_mid);if(text.charAt(finish)==pattern.charAt(pattern.length-1)){rd[finish]=(1<<(d+1))-1}else{rd[finish]=(1<<d)-1}for(var j=finish-1;j>=start;j--){if(d===0){rd[j]=((rd[j+1]<<1)|1)&s[text.charAt(j)]}else{rd[j]=((rd[j+1]<<1)|1)&s[text.charAt(j)]|((last_rd[j+1]<<1)|1)|((last_rd[j]<<1)|1)|last_rd[j+1]}if(rd[j]&matchmask){var score=match_bitapScore(d,j);if(score<=score_threshold){score_threshold=score;best_loc=j;if(j>loc){start=Math.max(0,loc-(j-loc))}else{break}}}}if(match_bitapScore(d+1,loc)>score_threshold){break}last_rd=rd}return best_loc};diff_match_patch.prototype.match_alphabet=function(pattern){var s=Object();for(var i=0;i<pattern.length;i++){s[pattern.charAt(i)]=0}for(var i=0;i<pattern.length;i++){s[pattern.charAt(i)]|=1<<(pattern.length-i-1)}return s};diff_match_patch.prototype.patch_addContext=function(patch,text){var pattern=text.substring(patch.start2,patch.start2+patch.length1);var padding=0;while(text.indexOf(pattern)!=text.lastIndexOf(pattern)&&pattern.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin){padding+=this.Patch_Margin;pattern=text.substring(patch.start2-padding,patch.start2+patch.length1+padding)}padding+=this.Patch_Margin;var prefix=text.substring(patch.start2-padding,patch.start2);if(prefix!==''){patch.diffs.unshift([DIFF_EQUAL,prefix])}var suffix=text.substring(patch.start2+patch.length1,patch.start2+patch.length1+padding);if(suffix!==''){patch.diffs.push([DIFF_EQUAL,suffix])}patch.start1-=prefix.length;patch.start2-=prefix.length;patch.length1+=prefix.length+suffix.length;patch.length2+=prefix.length+suffix.length};diff_match_patch.prototype.patch_make=function(text1,text2,opt_diffs){var diffs;if(typeof opt_diffs!='undefined'){diffs=opt_diffs}else{diffs=this.diff_main(text1,text2,true);if(diffs.length>2){this.diff_cleanupSemantic(diffs);this.diff_cleanupEfficiency(diffs)}}if(diffs.length===0){return[]}var patches=[];var patch=new patch_obj();var char_count1=0;var char_count2=0;var prepatch_text=text1;var postpatch_text=text1;for(var x=0;x<diffs.length;x++){var diff_type=diffs[x][0];var diff_text=diffs[x][1];if(patch.diffs.length===0&&diff_type!==DIFF_EQUAL){patch.start1=char_count1;patch.start2=char_count2}if(diff_type===DIFF_INSERT){patch.diffs.push(diffs[x]);patch.length2+=diff_text.length;postpatch_text=postpatch_text.substring(0,char_count2)+diff_text+postpatch_text.substring(char_count2)}else if(diff_type===DIFF_DELETE){patch.length1+=diff_text.length;patch.diffs.push(diffs[x]);postpatch_text=postpatch_text.substring(0,char_count2)+postpatch_text.substring(char_count2+diff_text.length)}else if(diff_type===DIFF_EQUAL&&diff_text.length<=2*this.Patch_Margin&&patch.diffs.length!==0&&diffs.length!=x+1){patch.diffs.push(diffs[x]);patch.length1+=diff_text.length;patch.length2+=diff_text.length}if(diff_type===DIFF_EQUAL&&diff_text.length>=2*this.Patch_Margin){if(patch.diffs.length!==0){this.patch_addContext(patch,prepatch_text);patches.push(patch);patch=new patch_obj();prepatch_text=postpatch_text}}if(diff_type!==DIFF_INSERT){char_count1+=diff_text.length}if(diff_type!==DIFF_DELETE){char_count2+=diff_text.length}}if(patch.diffs.length!==0){this.patch_addContext(patch,prepatch_text);patches.push(patch)}return patches};diff_match_patch.prototype.patch_apply=function(patches,text){this.patch_splitMax(patches);var results=[];var delta=0;for(var x=0;x<patches.length;x++){var expected_loc=patches[x].start2+delta;var text1=this.diff_text1(patches[x].diffs);var start_loc=this.match_main(text,text1,expected_loc);if(start_loc===null){results.push(false)}else{results.push(true);delta=start_loc-expected_loc;var text2=text.substring(start_loc,start_loc+text1.length);if(text1==text2){text=text.substring(0,start_loc)+this.diff_text2(patches[x].diffs)+text.substring(start_loc+text1.length)}else{var diffs=this.diff_main(text1,text2,false);this.diff_cleanupSemanticLossless(diffs);var index1=0;var index2;for(var y=0;y<patches[x].diffs.length;y++){var mod=patches[x].diffs[y];if(mod[0]!==DIFF_EQUAL){index2=this.diff_xIndex(diffs,index1)}if(mod[0]===DIFF_INSERT){text=text.substring(0,start_loc+index2)+mod[1]+text.substring(start_loc+index2)}else if(mod[0]===DIFF_DELETE){text=text.substring(0,start_loc+index2)+text.substring(start_loc+this.diff_xIndex(diffs,index1+mod[1].length))}if(mod[0]!==DIFF_DELETE){index1+=mod[1].length}}}}}return[text,results]};diff_match_patch.prototype.patch_splitMax=function(patches){for(var x=0;x<patches.length;x++){if(patches[x].length1>this.Match_MaxBits){var bigpatch=patches[x];patches.splice(x,1);var patch_size=this.Match_MaxBits;var start1=bigpatch.start1;var start2=bigpatch.start2;var precontext='';while(bigpatch.diffs.length!==0){var patch=new patch_obj();var empty=true;patch.start1=start1-precontext.length;patch.start2=start2-precontext.length;if(precontext!==''){patch.length1=patch.length2=precontext.length;patch.diffs.push([DIFF_EQUAL,precontext])}while(bigpatch.diffs.length!==0&&patch.length1<patch_size-this.Patch_Margin){var diff_type=bigpatch.diffs[0][0];var diff_text=bigpatch.diffs[0][1];if(diff_type===DIFF_INSERT){patch.length2+=diff_text.length;start2+=diff_text.length;patch.diffs.push(bigpatch.diffs.shift());empty=false}else{diff_text=diff_text.substring(0,patch_size-patch.length1-this.Patch_Margin);patch.length1+=diff_text.length;start1+=diff_text.length;if(diff_type===DIFF_EQUAL){patch.length2+=diff_text.length;start2+=diff_text.length}else{empty=false}patch.diffs.push([diff_type,diff_text]);if(diff_text==bigpatch.diffs[0][1]){bigpatch.diffs.shift()}else{bigpatch.diffs[0][1]=bigpatch.diffs[0][1].substring(diff_text.length)}}}precontext=this.diff_text2(patch.diffs);precontext=precontext.substring(precontext.length-this.Patch_Margin);var postcontext=this.diff_text1(bigpatch.diffs).substring(0,this.Patch_Margin);if(postcontext!==''){patch.length1+=postcontext.length;patch.length2+=postcontext.length;if(patch.diffs.length!==0&&patch.diffs[patch.diffs.length-1][0]===DIFF_EQUAL){patch.diffs[patch.diffs.length-1][1]+=postcontext}else{patch.diffs.push([DIFF_EQUAL,postcontext])}}if(!empty){patches.splice(x++,0,patch)}}}}};diff_match_patch.prototype.patch_toText=function(patches){var text=[];for(var x=0;x<patches.length;x++){text.push(patches[x])}return text.join('')};diff_match_patch.prototype.patch_fromText=function(textline){var patches=[];var text=textline.split('\n');while(text.length!==0){var m=text[0].match(/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/);if(!m){return alert('Invalid patch string:\n'+text[0])}var patch=new patch_obj();patches.push(patch);patch.start1=parseInt(m[1],10);if(m[2]===''){patch.start1--;patch.length1=1}else if(m[2]=='0'){patch.length1=0}else{patch.start1--;patch.length1=parseInt(m[2],10)}patch.start2=parseInt(m[3],10);if(m[4]===''){patch.start2--;patch.length2=1}else if(m[4]=='0'){patch.length2=0}else{patch.start2--;patch.length2=parseInt(m[4],10)}text.shift();while(text.length!==0){var sign=text[0].charAt(0);var line=decodeURIComponent(text[0].substring(1));if(sign=='-'){patch.diffs.push([DIFF_DELETE,line])}else if(sign=='+'){patch.diffs.push([DIFF_INSERT,line])}else if(sign==' '){patch.diffs.push([DIFF_EQUAL,line])}else if(sign=='@'){break}else if(sign===''){}else{return alert('Invalid patch mode: "'+sign+'"\n'+line)}text.shift()}}return patches};function patch_obj(){this.diffs=[];this.start1=null;this.start2=null;this.length1=0;this.length2=0}patch_obj.prototype.toString=function(){var coords1,coords2;if(this.length1===0){coords1=this.start1+',0'}else if(this.length1==1){coords1=this.start1+1}else{coords1=(this.start1+1)+','+this.length1}if(this.length2===0){coords2=this.start2+',0'}else if(this.length2==1){coords2=this.start2+1}else{coords2=(this.start2+1)+','+this.length2}var txt=['@@ -',coords1,' +',coords2,' @@\n'];for(var x=0;x<this.diffs.length;x++){switch(this.diffs[x][0]){case DIFF_DELETE:txt.push('-');break;case DIFF_EQUAL:txt.push(' ');break;case DIFF_INSERT:txt.push('+');break;default:alert('Invalid diff operation in patch_obj.toString()')}txt.push(encodeURI(this.diffs[x][1]),'\n')}return txt.join('').replace(/%20/g,' ')};
@@ -0,0 +1,70 @@
1
+ describe('An example model', {
2
+ before_each : function() {
3
+ //fake a record - just an anonymous object with a data.id
4
+ record = {data: {id: 1}};
5
+ },
6
+
7
+ 'should set the class_name correctly': function() {
8
+ value_of(AgentPageTemplate.class_name).should_be('AgentPageTemplate');
9
+ },
10
+
11
+ 'should set the controller_name correctly': function() {
12
+ value_of(AgentPageTemplate.controller_name).should_be('AgentPageTemplatesController');
13
+ },
14
+
15
+ 'should set the foreign_key_name correctly': function() {
16
+ value_of(AgentPageTemplate.foreign_key_name).should_be('agent_page_template_id');
17
+ },
18
+
19
+ 'should set the parametized foreign_key_name correctly': function() {
20
+ value_of(AgentPageTemplate.parametized_foreign_key_name).should_be(':agent_page_template_id');
21
+ },
22
+
23
+ 'should set the human_plural_name correctly': function() {
24
+ value_of(AgentPageTemplate.human_plural_name).should_be('Agent Page Templates');
25
+ },
26
+
27
+ 'should set the human_singular_name correctly': function() {
28
+ value_of(AgentPageTemplate.human_singular_name).should_be('Agent Page Template');
29
+ },
30
+
31
+ 'should set the underscore_name correctly': function() {
32
+ value_of(AgentPageTemplate.underscore_name).should_be('agent_page_template');
33
+ },
34
+
35
+ 'should set the url_name correctly': function() {
36
+ value_of(AgentPageTemplate.url_name).should_be('agent_page_templates');
37
+ },
38
+
39
+ 'should return the correct tree url': function() {
40
+ value_of(AgentPageTemplate.treeUrl()).should_be('/admin/agent_page_templates/tree.ext_json');
41
+ },
42
+
43
+ 'should return the correct tree reorder url': function() {
44
+ value_of(AgentPageTemplate.treeReorderUrl(record)).should_be('/admin/agent_page_templates/reorder/1.ext_json');
45
+ },
46
+
47
+ 'should return the correct data url for a given object': function() {
48
+ value_of(AgentPageTemplate.singleDataUrl(record)).should_be('/admin/agent_page_templates/1.ext_json');
49
+ },
50
+
51
+ 'should return the correct data url for the collection': function() {
52
+ value_of(AgentPageTemplate.collectionDataUrl()).should_be('/admin/agent_page_templates.ext_json');
53
+ },
54
+
55
+ 'should return the correct edit url for a given record': function() {
56
+ value_of(AgentPageTemplate.editUrl(record)).should_be('agent_page_templates/Edit/1');
57
+ },
58
+
59
+ 'should return the correct show url for a given record': function() {
60
+ value_of(AgentPageTemplate.showUrl(record)).should_be('agent_page_templates/Edit/1');
61
+ },
62
+
63
+ 'should return the correct new url': function() {
64
+ value_of(AgentPageTemplate.newUrl()).should_be('agent_page_templates/New');
65
+ },
66
+
67
+ 'should return the correct url for the collection': function() {
68
+ value_of(AgentPageTemplate.collectionUrl()).should_be('agent_page_templates/Index');
69
+ }
70
+ });
@@ -0,0 +1,38 @@
1
+ describe('A Route', {
2
+ before_each: function() {
3
+ r = new ExtMVC.Route(':controller/:action/:id');
4
+ },
5
+
6
+ 'should return whether or not it matches a given URL': function() {
7
+ value_of(r.recognises('someroute')).should_be(false);
8
+ value_of(r.recognises('c/a/id')).should_be(true);
9
+ },
10
+
11
+ "should have an array of all matching segments found in the matching string": function() {
12
+ var obj = r.paramsInMatchString;
13
+ value_of(obj).should_be([':controller', ':action', ':id']);
14
+ },
15
+
16
+ "should return false from matches_for when the route doesn't match" : function() {
17
+ value_of(r.matchesFor('a')).should_be(false);
18
+ },
19
+
20
+ "should return the correct params hash from a matching url": function() {
21
+ var obj = r.matchesFor('con/act/1');
22
+ value_of(obj[":controller"]).should_be('con');
23
+ value_of(obj[":action"]).should_be('act');
24
+ value_of(obj[":id"]).should_be('1');
25
+ },
26
+
27
+ 'return an object with all extra passed params' : function() {
28
+ r = new ExtMVC.Route(':controller/:action/:id', {':some_key': 'some value'});
29
+ obj = r.matchesFor('c/a/id');
30
+
31
+ value_of(obj[':some_key']).should_be('some value');
32
+ },
33
+
34
+ 'should convert mapping "regexes" into actual regexes useful for matching' : function() {
35
+ expected = /^([a-zA-Z0-9\_,]+)\/([a-zA-Z0-9\_,]+)\/([a-zA-Z0-9\_,]+)$/;
36
+ value_of(r.matcherRegex).should_be(expected);
37
+ }
38
+ });
@@ -0,0 +1,59 @@
1
+ describe('The Router', {
2
+ before_each : function() {
3
+ map = new ExtMVC.Router({});
4
+ },
5
+
6
+ 'routes actions for :controller/:action' : function() {
7
+ map.connect(':controller/:action');
8
+ obj = map.recognise('controller_name/action_name');
9
+
10
+ value_of(obj[':controller']).should_be('controller_name');
11
+ value_of(obj[':action']).should_be('action_name');
12
+ },
13
+
14
+ 'routes params for :controller/:action/:id' : function() {
15
+ map.connect(':controller/:action/:id');
16
+ obj = map.recognise('controller_name/action_name/1');
17
+
18
+ value_of(obj[':controller']).should_be('controller_name');
19
+ value_of(obj[':action']).should_be('action_name');
20
+ value_of(obj[':id']).should_be('1');
21
+ },
22
+
23
+ //regression test to make sure underscore bug doesn't come back
24
+ 'routes params for :controller/:action/:underscored_id' : function() {
25
+ map.connect(':controller/:action/:underscored_id');
26
+ obj = map.recognise('controller_name/action_name/1');
27
+
28
+ value_of(obj[':controller']).should_be('controller_name');
29
+ value_of(obj[':action']).should_be('action_name');
30
+ value_of(obj[':underscored_id']).should_be('1');
31
+ },
32
+
33
+ 'routes params for :controller/:action/:id when there are multiple IDs' : function() {
34
+ map.connect(':controller/:action/:id');
35
+ obj = map.recognise('controller_name/action_name/1,2,3');
36
+
37
+ value_of(obj[':controller']).should_be('controller_name');
38
+ value_of(obj[':action']).should_be('action_name');
39
+ value_of(obj[':id']).should_be('1,2,3');
40
+ },
41
+
42
+ 'routes params for :controller/:action with other routes defined' : function() {
43
+ map.connect(':controller/:action/:id');
44
+ map.connect(':controller/:action');
45
+ obj = map.recognise('controller_name/action_name');
46
+
47
+ value_of(obj[':controller']).should_be('controller_name');
48
+ value_of(obj[':action']).should_be('action_name');
49
+ },
50
+
51
+ 'route params for more specific regexes' : function() {
52
+ map.connect('namespace/:controller/:action');
53
+ map.connect(':controller/:action/:id');
54
+ obj = map.recognise('namespace/controller_name/action_name');
55
+
56
+ value_of(obj[':controller']).should_be('controller_name');
57
+ value_of(obj[':action']).should_be('action_name');
58
+ }
59
+ });
@@ -0,0 +1,22 @@
1
+ describe('String methods', {
2
+ 'should capitalise a word': function() {
3
+ word = 'test';
4
+ value_of(String.capitalize(word)).should_be('Test');
5
+ },
6
+ 'should capitalise only the first word in a sentence': function() {
7
+ sentence = "the sentence";
8
+ value_of(String.capitalize(sentence)).should_be("The sentence");
9
+ },
10
+ 'should titleize a sentence': function() {
11
+ sentence = "this is a sentence";
12
+ value_of(String.titleize(sentence)).should_be("This Is A Sentence");
13
+ },
14
+ 'should camelize a simple string': function() {
15
+ underscored_string = 'classname';
16
+ value_of(String.camelize(underscored_string)).should_be('Classname');
17
+ },
18
+ 'should camelize a long string': function() {
19
+ underscored_string = 'long_class_name';
20
+ value_of(String.camelize(underscored_string)).should_be('LongClassName');
21
+ }
22
+ });
@@ -0,0 +1,111 @@
1
+ /**
2
+ * @class ExtMVC.test.JSpecFormatter
3
+ * @extends Object
4
+ * A JSpec formatter which can be used to extract failure data from JSpec
5
+ */
6
+ ExtMVC.test.JSpecFormatter = Ext.extend(Object, {
7
+
8
+ constructor: function(results, options) {
9
+ this.suites = results.suites;
10
+ },
11
+
12
+ /**
13
+ * Returns an array of all failing Spec objects for all suites
14
+ */
15
+ getFailingSpecs: function(suites) {
16
+ var suites = suites || this.suites;
17
+ var failures = [];
18
+
19
+ Ext.each(suites, function(suite) {
20
+ failures = failures.concat(this.getFailuresForSuite(suite));
21
+
22
+ if (suite.hasSuites()) {
23
+ failures = failures.concat(this.getFailingSpecs(suite.suites));
24
+ }
25
+ }, this);
26
+
27
+ return failures;
28
+ },
29
+
30
+ /**
31
+ * Returns an array of failing Spec objects for a given suite
32
+ */
33
+ getFailuresForSuite: function(suite) {
34
+ if (suite.ran && suite.passed()) {
35
+ return [];
36
+ } else {
37
+ var failures = [];
38
+
39
+ Ext.each(suite.specs, function(spec) {
40
+ if (!spec.passed()) {
41
+ Ext.apply(spec, {
42
+ code: this.bodyContents(spec.body)
43
+ });
44
+
45
+ failures.push(spec);
46
+ }
47
+ }, this);
48
+
49
+ return failures;
50
+ }
51
+ },
52
+
53
+ bodyContents: function(body) {
54
+ return JSpec.
55
+ escape(JSpec.contentsOf(body)).
56
+ replace(/^ */gm, function(a){
57
+ return (new Array(Math.round(a.length / 3))).join(' ');
58
+ }).
59
+ replace("\n", '<br/>');
60
+ }
61
+ });
62
+
63
+ // DOM : function(results, options) {
64
+ // var id = option('reportToId') || 'jspec'
65
+ // var report = document.getElementById(id)
66
+ // var failuresOnly = option('failuresOnly')
67
+ // var classes = results.stats.failures ? 'has-failures' : ''
68
+ // if (!report) throw 'JSpec requires the element #' + id + ' to output its reports'
69
+ //
70
+ // var markup =
71
+ // '<div id="jspec-report" class="' + classes + '"><div class="heading"> \
72
+ // <span class="passes">Passes: <em>' + results.stats.passes + '</em></span> \
73
+ // <span class="failures">Failures: <em>' + results.stats.failures + '</em></span> \
74
+ // </div><table class="suites">'
75
+ //
76
+ // bodyContents = function(body) {
77
+ // return JSpec.
78
+ // escape(JSpec.contentsOf(body)).
79
+ // replace(/^ */gm, function(a){ return (new Array(Math.round(a.length / 3))).join(' ') }).
80
+ // replace("\n", '<br/>')
81
+ // }
82
+ //
83
+ // renderSuite = function(suite) {
84
+ // var displaySuite = failuresOnly ? suite.ran && !suite.passed() : suite.ran
85
+ // if (displaySuite && suite.hasSpecs()) {
86
+ // markup += '<tr class="description"><td colspan="2">' + escape(suite.description) + '</td></tr>'
87
+ // each(suite.specs, function(i, spec){
88
+ // markup += '<tr class="' + (i % 2 ? 'odd' : 'even') + '">'
89
+ // if (spec.requiresImplementation())
90
+ // markup += '<td class="requires-implementation" colspan="2">' + escape(spec.description) + '</td>'
91
+ // else if (spec.passed() && !failuresOnly)
92
+ // markup += '<td class="pass">' + escape(spec.description)+ '</td><td>' + spec.assertionsGraph() + '</td>'
93
+ // else if(!spec.passed())
94
+ // markup += '<td class="fail">' + escape(spec.description) + ' <em>' + spec.failure().message + '</em>' + '</td><td>' + spec.assertionsGraph() + '</td>'
95
+ // markup += '<tr class="body"><td colspan="2"><pre>' + bodyContents(spec.body) + '</pre></td></tr>'
96
+ // })
97
+ // markup += '</tr>'
98
+ // }
99
+ // }
100
+ //
101
+ // renderSuites = function(suites) {
102
+ // each(suites, function(suite){
103
+ // renderSuite(suite)
104
+ // if (suite.hasSuites()) renderSuites(suite.suites)
105
+ // })
106
+ // }
107
+ //
108
+ // renderSuites(results.suites)
109
+ // markup += '</table></div>'
110
+ // report.innerHTML = markup
111
+ // },
@@ -0,0 +1,181 @@
1
+ /**
2
+ * @class ExtMVC.test.TestClient
3
+ * @extends Ext.util.Observable
4
+ * Simple client which interacts with a test server, polling for new tests to run and posting results
5
+ */
6
+ ExtMVC.test.TestClient = Ext.extend(Ext.util.Observable, {
7
+
8
+ constructor: function(config) {
9
+ config = config || {};
10
+
11
+ Ext.applyIf(config, {
12
+ /**
13
+ * @property currentCallbackId
14
+ * @type Number
15
+ * The current callback number. This is incremented on every request, and allows for a unique
16
+ */
17
+ currentCallbackId: 1,
18
+
19
+ /**
20
+ * @property lastChangesReceived
21
+ * @type Date
22
+ * Time the last changes array was received from the server
23
+ */
24
+ lastChangesReceived: new Date()
25
+ });
26
+
27
+ Ext.apply(this, config);
28
+
29
+ ExtMVC.test.TestClient.superclass.constructor.apply(this, arguments);
30
+
31
+ this.initEvents();
32
+ this.initListeners();
33
+
34
+ /**
35
+ * @property runner
36
+ * @type ExtMVC.test.TestRunner
37
+ * The test runner instance used to actually run the tests
38
+ */
39
+ this.runner = new ExtMVC.test.TestRunner();
40
+ this.runner.on('finished', this.postResults, this);
41
+
42
+ this.loadTestFiles();
43
+
44
+ Ext.TaskMgr.start({
45
+ interval: 1000,
46
+ scope : this,
47
+ run : function() {
48
+ this.jsonpRequest("http://192.168.3.2:5000/changes", {
49
+ since: Math.floor(this.lastChangesReceived.getTime() / 1000)
50
+ }, this.onChangePoll);
51
+ }
52
+ });
53
+ },
54
+
55
+ /**
56
+ * Sets up events emitted by TestClient
57
+ */
58
+ initEvents: function() {
59
+ this.addEvents(
60
+ /**
61
+ * @event results-posted
62
+ * Fires when results have been successfully sent to the test server
63
+ * @param {Object} stats The stats object that was sent
64
+ */
65
+ 'results-posted',
66
+
67
+ /**
68
+ * @event changes-received
69
+ * Fires when the server has notified this client that files have changed and the appropriate
70
+ * suites must be run again
71
+ * @param {Array} changes The files that have changed
72
+ */
73
+ 'changes-received'
74
+ );
75
+ },
76
+
77
+ /**
78
+ * Sets up internal listeners
79
+ */
80
+ initListeners: function() {
81
+ this.on('changes-received', this.onChangesReceived, this);
82
+ },
83
+
84
+ /**
85
+ * Retrieves the array of all test files from the server, then tells JSpec to run them
86
+ * @param {Boolean} autoRun True to run test files as soon as they are loaded (defaults to true)
87
+ */
88
+ loadTestFiles: function() {
89
+ this.jsonpRequest('http://192.168.3.2:5000/all_test_files', {}, function(response) {
90
+ this.runner.addTests(response.files);
91
+ this.runner.runTests();
92
+ });
93
+ },
94
+
95
+ /**
96
+ * Posts results back to the server
97
+ * @param {Object} stats Stats object
98
+ */
99
+ postResults: function(stats) {
100
+ this.jsonpRequest('http://192.168.3.2:5000/results', stats, function() {
101
+ this.fireEvent('results-posted', stats);
102
+
103
+ var runner = this.runner;
104
+
105
+ if (stats.failures == 0 && runner.hasRecentFailures && !runner.fullRun) {
106
+ console.log('running full suite after failures');
107
+ // runner.runTests();
108
+ };
109
+ });
110
+ },
111
+
112
+ /**
113
+ * Called after the client has polled the server for changes. Fires the 'changes-received' event if any files have changed
114
+ * @param {Object} response The server response, should include a 'changes' property with an array of changes
115
+ */
116
+ onChangePoll: function(response) {
117
+ var changes = response.files;
118
+
119
+ if (Ext.isArray(changes) && changes.length > 0) {
120
+ this.fireEvent('changes-received', changes);
121
+ };
122
+ },
123
+
124
+ /**
125
+ * Called when the server has indicated that app or spec files have been modified.
126
+ * Runs the test suite again.
127
+ * @param {Array} changes The array of changed file names
128
+ */
129
+ onChangesReceived: function(changes) {
130
+ this.lastChangesReceived = new Date();
131
+ this.runner.runTests(changes);
132
+ },
133
+
134
+ jsonpRequest: function(url, params, callback, scope) {
135
+ scope = scope || this;
136
+
137
+ var head = document.getElementsByTagName("head")[0];
138
+
139
+ var callbackName = "stProxyCallback" + this.currentCallbackId;
140
+ this.currentCallbackId += 1;
141
+
142
+ window[callbackName] = function() {
143
+ callback.apply(scope, arguments);
144
+ };
145
+
146
+ var urlParams = ["callback=" + callbackName];
147
+
148
+ Ext.iterate(params, function(key, value) {
149
+ urlParams.push(String.format("{0}={1}", key, value));
150
+ }, this);
151
+
152
+ url = String.format("{0}?{1}", url, urlParams.join("&"));
153
+
154
+ head.appendChild(
155
+ this.buildScriptTag(url)
156
+ );
157
+ },
158
+
159
+
160
+ buildScriptTag: function(filename, callback) {
161
+ callback = callback || Ext.emptyFn;
162
+
163
+ var script = document.createElement('script');
164
+ script.type = "text/javascript";
165
+ script.src = filename;
166
+
167
+ //IE has a different way of handling <script> loads, so we need to check for it here
168
+ if (script.readyState) {
169
+ script.onreadystatechange = function(){
170
+ if (script.readyState == "loaded" || script.readyState == "complete") {
171
+ script.onreadystatechange = null;
172
+ callback();
173
+ }
174
+ };
175
+ } else {
176
+ script.onload = callback;
177
+ }
178
+
179
+ return script;
180
+ }
181
+ });