extjs-mvc 0.3.10 → 0.4.0.a

Sign up to get free protection for your applications and to get access to all the features.
Files changed (204) hide show
  1. data/LICENSE +1 -1
  2. data/README.rdoc +5 -173
  3. data/Rakefile +18 -20
  4. data/VERSION +1 -1
  5. data/bin/xmvc +13 -0
  6. data/lib/extjs-mvc/README +20 -0
  7. data/lib/extjs-mvc/builder.rb +83 -0
  8. data/lib/extjs-mvc/builders/all_builder.rb +15 -0
  9. data/lib/extjs-mvc/builders/app_builder.rb +36 -0
  10. data/lib/extjs-mvc/builders/base.rb +138 -0
  11. data/lib/extjs-mvc/builders/css_builder.rb +36 -0
  12. data/lib/extjs-mvc/builders/docs_builder.rb +20 -0
  13. data/lib/extjs-mvc/builders/mvc_builder.rb +33 -0
  14. data/lib/extjs-mvc/builders/plugin_builder.rb +53 -0
  15. data/lib/extjs-mvc/cli.rb +52 -0
  16. data/lib/extjs-mvc/generator.rb +79 -0
  17. data/lib/extjs-mvc/generators/app.rb +57 -0
  18. data/lib/extjs-mvc/generators/base.rb +53 -0
  19. data/lib/extjs-mvc/generators/controller.rb +41 -0
  20. data/lib/extjs-mvc/generators/model.rb +41 -0
  21. data/lib/extjs-mvc/generators/scaffold.rb +17 -0
  22. data/lib/extjs-mvc/generators/templates/Controller.js +17 -0
  23. data/lib/extjs-mvc/generators/templates/Model.js +9 -0
  24. data/lib/extjs-mvc/generators/templates/ModelSpec.js +12 -0
  25. data/lib/extjs-mvc/generators/templates/View.js +16 -0
  26. data/lib/extjs-mvc/generators/templates/_Action.js +7 -0
  27. data/lib/extjs-mvc/generators/templates/app/README.rdoc +152 -0
  28. data/lib/extjs-mvc/generators/templates/app/app/App.js +64 -0
  29. data/lib/extjs-mvc/generators/templates/app/app/controllers/ApplicationController.js +10 -0
  30. data/lib/extjs-mvc/generators/templates/app/app/controllers/HomeController.js +10 -0
  31. data/lib/extjs-mvc/generators/templates/app/app/views/home/Index.js +17 -0
  32. data/lib/extjs-mvc/generators/templates/app/app/views/layout/Menu.js +23 -0
  33. data/lib/extjs-mvc/generators/templates/app/config/application.js +1 -0
  34. data/lib/extjs-mvc/generators/templates/app/config/boot.js +67 -0
  35. data/lib/extjs-mvc/generators/templates/app/config/build.xml +77 -0
  36. data/lib/extjs-mvc/generators/templates/app/config/database.js +4 -0
  37. data/lib/extjs-mvc/generators/templates/app/config/environment.json +58 -0
  38. data/lib/extjs-mvc/generators/templates/app/config/environments/development.json +1 -0
  39. data/lib/extjs-mvc/generators/templates/app/config/environments/production.json +4 -0
  40. data/lib/extjs-mvc/generators/templates/app/config/routes.js +27 -0
  41. data/lib/extjs-mvc/generators/templates/app/config/settings.yml +3 -0
  42. data/lib/extjs-mvc/generators/templates/app/public/index.html +19 -0
  43. data/lib/extjs-mvc/generators/templates/app/public/stylesheets/ext-mvc-all.css +49 -0
  44. data/{test/active_record_test.rb → lib/extjs-mvc/generators/templates/app/spec/SpecHelper.js} +0 -0
  45. data/lib/extjs-mvc/generators/templates/app/spec/index.html +66 -0
  46. data/lib/extjs-mvc/generators/templates/app/vendor/screw-unit/EXAMPLE.html +68 -0
  47. data/lib/extjs-mvc/generators/templates/app/vendor/screw-unit/LICENSE +22 -0
  48. data/lib/extjs-mvc/generators/templates/app/vendor/screw-unit/README.markdown +307 -0
  49. data/lib/extjs-mvc/generators/templates/app/vendor/screw-unit/lib/jquery-1.2.3.js +3408 -0
  50. data/lib/extjs-mvc/generators/templates/app/vendor/screw-unit/lib/jquery.fn.js +29 -0
  51. data/lib/extjs-mvc/generators/templates/app/vendor/screw-unit/lib/jquery.print.js +108 -0
  52. data/lib/extjs-mvc/generators/templates/app/vendor/screw-unit/lib/screw.assets.js +36 -0
  53. data/lib/extjs-mvc/generators/templates/app/vendor/screw-unit/lib/screw.behaviors.js +91 -0
  54. data/lib/extjs-mvc/generators/templates/app/vendor/screw-unit/lib/screw.builder.js +80 -0
  55. data/lib/extjs-mvc/generators/templates/app/vendor/screw-unit/lib/screw.css +90 -0
  56. data/lib/extjs-mvc/generators/templates/app/vendor/screw-unit/lib/screw.events.js +42 -0
  57. data/lib/extjs-mvc/generators/templates/app/vendor/screw-unit/lib/screw.matchers.js +145 -0
  58. data/lib/extjs-mvc/generators/templates/app/vendor/screw-unit/lib/screw.server.js +21 -0
  59. data/lib/extjs-mvc/generators/templates/app/vendor/screw-unit/spec/behaviors_spec.js +178 -0
  60. data/lib/extjs-mvc/generators/templates/app/vendor/screw-unit/spec/matchers_spec.js +237 -0
  61. data/lib/extjs-mvc/generators/templates/app/vendor/screw-unit/spec/print_spec.js +119 -0
  62. data/{test/controller_test.rb → lib/extjs-mvc/generators/templates/app/vendor/screw-unit/spec/spec_helper.js} +0 -0
  63. data/lib/extjs-mvc/generators/templates/app/vendor/screw-unit/spec/suite.html +18 -0
  64. data/lib/extjs-mvc/generators/templates/scaffold/ScaffoldController.js +18 -0
  65. data/lib/extjs-mvc/generators/view.rb +29 -0
  66. data/lib/extjs-mvc/plugin.rb +105 -0
  67. data/lib/extjs-mvc/scripts.rb +15 -0
  68. data/lib/extjs-mvc/settings.rb +75 -0
  69. data/lib/extjs-mvc/setup.rb +5 -0
  70. data/lib/extjs-mvc/stats.rb +241 -0
  71. data/lib/extjs-mvc/test.rb +11 -0
  72. data/lib/extjs-mvc/testserver.ru +95 -0
  73. data/lib/extjs-mvc/ui.rb +58 -0
  74. data/lib/extjs-mvc/update.rb +73 -0
  75. data/lib/extjs-mvc.rb +70 -32
  76. data/lib/js/App.js +219 -0
  77. data/lib/js/MVC.js +260 -0
  78. data/lib/js/Presenter.js +52 -0
  79. data/lib/js/README.rdoc +69 -0
  80. data/lib/js/build +21 -0
  81. data/lib/js/controller/Controller.js +278 -0
  82. data/lib/js/controller/CrudController.js +460 -0
  83. data/lib/js/lib/Array.js +26 -0
  84. data/lib/js/lib/Booter.js +415 -0
  85. data/lib/js/lib/ClassManager.js +191 -0
  86. data/lib/js/lib/ControllerClassManager.js +95 -0
  87. data/lib/js/lib/Dependencies.js +44 -0
  88. data/lib/js/lib/DispatchMatcher.js +98 -0
  89. data/lib/js/lib/Dispatcher.js +129 -0
  90. data/lib/js/lib/Environment.js +43 -0
  91. data/lib/js/lib/Inflector.js +138 -0
  92. data/lib/js/lib/ModelClassManager.js +19 -0
  93. data/lib/js/lib/Route.js +139 -0
  94. data/lib/js/lib/Router.js +282 -0
  95. data/lib/js/lib/String.js +94 -0
  96. data/lib/js/lib/ViewClassManager.js +229 -0
  97. data/lib/js/lib/notes.txt +32 -0
  98. data/lib/js/model/AdapterManager.js +30 -0
  99. data/lib/js/model/Association.js +26 -0
  100. data/lib/js/model/Base.js +63 -0
  101. data/lib/js/model/BelongsToAssociation.js +116 -0
  102. data/lib/js/model/Cache.js +131 -0
  103. data/lib/js/model/HasManyAssociation.js +160 -0
  104. data/lib/js/model/Model.js +331 -0
  105. data/lib/js/model/UrlBuilder.js +106 -0
  106. data/lib/js/model/adapters/AbstractAdapter.js +296 -0
  107. data/lib/js/model/adapters/MemoryAdapter.js +103 -0
  108. data/lib/js/model/adapters/RESTAdapter.js +345 -0
  109. data/lib/js/model/adapters/RESTJSONAdapter.js +68 -0
  110. data/lib/js/model/adapters/notes.txt +42 -0
  111. data/lib/js/model/associations/Association.js +192 -0
  112. data/lib/js/model/associations/notes.txt +87 -0
  113. data/lib/js/model/validations/Errors.js +136 -0
  114. data/lib/js/model/validations/Plugin.js +139 -0
  115. data/lib/js/model/validations/Validations.js +276 -0
  116. data/lib/js/notes/Charts.graffle +0 -0
  117. data/lib/js/overrides/Ext.Component.js +21 -0
  118. data/lib/js/overrides/Ext.extend.js +142 -0
  119. data/lib/js/spec/Array.spec.js +15 -0
  120. data/lib/js/spec/ExtMVC.spec.js +65 -0
  121. data/lib/js/spec/Model.spec.js +370 -0
  122. data/lib/js/spec/OS.spec.js +83 -0
  123. data/lib/js/spec/Router.spec.js +99 -0
  124. data/lib/js/spec/SpecHelper.js +106 -0
  125. data/lib/js/spec/String.spec.js +83 -0
  126. data/lib/js/spec/model/AbstractAdapter.spec.js +49 -0
  127. data/lib/js/spec/model/Associations.spec.js +99 -0
  128. data/lib/js/spec/model/Cache.spec.js +5 -0
  129. data/lib/js/spec/model/RESTAdapter.spec.js +19 -0
  130. data/lib/js/spec/model/ValidationErrors.spec.js +64 -0
  131. data/lib/js/spec/model/Validations.spec.js +166 -0
  132. data/lib/js/spec/model/ValidationsPlugin.spec.js +108 -0
  133. data/lib/js/spec/suite.html +60 -0
  134. data/lib/js/specs-old/JSSpec.css +216 -0
  135. data/lib/js/specs-old/JSSpec.js +1512 -0
  136. data/lib/js/specs-old/all.html +66 -0
  137. data/lib/js/specs-old/base.js +14 -0
  138. data/lib/js/specs-old/controller.js +17 -0
  139. data/lib/js/specs-old/diff_match_patch.js +1 -0
  140. data/lib/js/specs-old/model.js +70 -0
  141. data/lib/js/specs-old/route.js +38 -0
  142. data/lib/js/specs-old/router.js +59 -0
  143. data/lib/js/specs-old/string.js +22 -0
  144. data/lib/js/testrunner/JSpecFormatter.js +111 -0
  145. data/lib/js/testrunner/TestClient.js +181 -0
  146. data/lib/js/testrunner/TestGrid.js +351 -0
  147. data/lib/js/testrunner/TestRunner.js +110 -0
  148. data/lib/js/testrunner/TestViewport.js +94 -0
  149. data/lib/js/vendor/screw-unit/EXAMPLE.html +68 -0
  150. data/lib/js/vendor/screw-unit/LICENSE +22 -0
  151. data/lib/js/vendor/screw-unit/README.markdown +307 -0
  152. data/lib/js/vendor/screw-unit/lib/jquery-1.2.3.js +3408 -0
  153. data/lib/js/vendor/screw-unit/lib/jquery.fn.js +29 -0
  154. data/lib/js/vendor/screw-unit/lib/jquery.print.js +108 -0
  155. data/lib/js/vendor/screw-unit/lib/screw.assets.js +36 -0
  156. data/lib/js/vendor/screw-unit/lib/screw.behaviors.js +91 -0
  157. data/lib/js/vendor/screw-unit/lib/screw.builder.js +80 -0
  158. data/lib/js/vendor/screw-unit/lib/screw.css +91 -0
  159. data/lib/js/vendor/screw-unit/lib/screw.events.js +42 -0
  160. data/lib/js/vendor/screw-unit/lib/screw.matchers.js +145 -0
  161. data/lib/js/vendor/screw-unit/lib/screw.server.js +21 -0
  162. data/lib/js/vendor/screw-unit/spec/behaviors_spec.js +178 -0
  163. data/lib/js/vendor/screw-unit/spec/matchers_spec.js +237 -0
  164. data/lib/js/vendor/screw-unit/spec/print_spec.js +119 -0
  165. data/{test/data_mapper_test.rb → lib/js/vendor/screw-unit/spec/spec_helper.js} +0 -0
  166. data/lib/js/vendor/screw-unit/spec/suite.html +18 -0
  167. data/lib/js/view/FormWindow.js +184 -0
  168. data/lib/js/view/HasManyEditorGridPanel.js +211 -0
  169. data/lib/js/view/scaffold/Edit.js +46 -0
  170. data/lib/js/view/scaffold/Index.js +561 -0
  171. data/lib/js/view/scaffold/New.js +20 -0
  172. data/lib/js/view/scaffold/ScaffoldFormPanel.js +255 -0
  173. data/test/helper.rb +10 -0
  174. data/test/test_extjs-mvc-gem.rb +7 -0
  175. metadata +232 -56
  176. data/README +0 -12
  177. data/lib/controller/controller.rb +0 -28
  178. data/lib/core_ext/array/extract_options.rb +0 -15
  179. data/lib/extjs/component.rb +0 -71
  180. data/lib/extjs/data/store.rb +0 -131
  181. data/lib/helpers/component.rb +0 -37
  182. data/lib/helpers/store.rb +0 -7
  183. data/lib/model/active_record.rb +0 -89
  184. data/lib/model/base.rb +0 -370
  185. data/lib/model/data_mapper.rb +0 -66
  186. data/lib/model/mongo_mapper.rb +0 -64
  187. data/lib/test/macros.rb +0 -20
  188. data/test/app/config/application.rb +0 -70
  189. data/test/app/config/database.yml +0 -3
  190. data/test/app/db/schema.rb +0 -75
  191. data/test/app/models/active_record/address.rb +0 -4
  192. data/test/app/models/active_record/data_type.rb +0 -3
  193. data/test/app/models/active_record/group.rb +0 -4
  194. data/test/app/models/active_record/house.rb +0 -4
  195. data/test/app/models/active_record/location.rb +0 -5
  196. data/test/app/models/active_record/person.rb +0 -4
  197. data/test/app/models/active_record/user.rb +0 -6
  198. data/test/app/models/active_record/user_group.rb +0 -4
  199. data/test/component_test.rb +0 -15
  200. data/test/debug.log +0 -2969
  201. data/test/model_test.rb +0 -526
  202. data/test/mongo_mapper_test.rb +0 -0
  203. data/test/store_test.rb +0 -0
  204. data/test/test_helper.rb +0 -32
data/lib/extjs-mvc.rb CHANGED
@@ -1,40 +1,78 @@
1
+ require 'fileutils'
2
+ require 'pathname'
3
+ require 'yaml'
4
+ require 'json'
5
+ require 'extlib/inflection'
6
+
1
7
  module ExtJS
2
- class MVC
3
- @@success_property = :success
4
- @@message_property = :message
5
- @@root = :data
6
- cattr_accessor :success_property
7
- cattr_accessor :message_property
8
- cattr_accessor :root
9
-
10
- require 'model/base'
11
-
12
- # Detect orm, include appropriate mixin.
13
- if defined?(ActiveRecord)
14
- require 'model/active_record'
15
- elsif defined?(DataMapper)
16
- require 'model/data_mapper'
17
- elsif defined?(MongoMapper)
18
- require 'model/mongo_mapper'
19
- else
20
- raise StandardError.new("extjs-mvc could not detect an ORM framework. Be sure to include your ORM framework before initializing extjs-mvc Gem.")
8
+ module MVC
9
+ VERSION = "0.4.0"
10
+
11
+ ROOT = File.dirname(__FILE__)
12
+
13
+ ##
14
+ # Do autoloads here
15
+ #
16
+ require 'extjs-mvc/settings'
17
+
18
+ autoload :UI, 'extjs-mvc/ui'
19
+ autoload :Generator, 'extjs-mvc/generator'
20
+ autoload :BuilderManager, 'extjs-mvc/builder'
21
+ autoload :Plugin, 'extjs-mvc/plugin'
22
+ autoload :Stats, 'extjs-mvc/stats'
23
+ autoload :Update, 'extjs-mvc/update'
24
+ autoload :Text, 'extjs-mvc/test'
25
+
26
+ class Error < StandardError
27
+ def self.status_code(code = nil)
28
+ return @code unless code
29
+ @code = code
21
30
  end
22
31
 
23
- # Rails-style Array#extract_options! used heavily
24
- if defined?(Merb)
25
- require 'core_ext/array/extract_options'
32
+ def status_code
33
+ self.class.status_code
26
34
  end
35
+ end
36
+
37
+ class AppNotFound < Error; status_code(1) ; end
38
+ class AppAlreadyExists < Error; status_code(2) ; end
39
+ class FileExists < Error; status_code(3) ; end
40
+ class BuilderError < Error; status_code(4) ; end
41
+
42
+
43
+
44
+ ##
45
+ # Add more error classes here
46
+ #
47
+ #class GemfileNotFound < BundlerError; status_code(10) ; end
48
+ #class GemNotFound < BundlerError; status_code(7) ; end
27
49
 
28
- # ExtJS Component and Store wrappers
29
- require 'extjs/component'
30
- require 'extjs/data/store'
50
+ class << self
51
+ attr_writer :ui
31
52
 
32
- # Component/Store view-helpers
33
- require 'helpers/component'
34
- require 'helpers/store'
35
-
36
- # Controller mixin. Works for both Rails and Merb.
37
- require 'controller/controller'
38
- end
53
+ def configure
54
+ @configured ||= begin
55
+ ##
56
+ # perform some config here?
57
+ #
58
+ #configure_gem_home_and_path
59
+ true
60
+ end
61
+ end
62
+
63
+ ##
64
+ # Ensure we're running within a rails app unless generating a new app ($ xmvc generate app foo)
65
+ #
66
+ def ensure_in_app
67
+ unless ARGV.empty? || ARGV.first == 'help' || (File.exists?('app') && File.exists?('config') && File.exists?('config/environment.json'))
68
+ raise ExtJS::MVC::AppNotFound.new("This command must be executed from the root of an extjs-mvc application")
69
+ end
70
+ end
71
+
72
+ def ui
73
+ @ui ||= UI.new
74
+ end
75
+ end
76
+ end
39
77
  end
40
78
 
data/lib/js/App.js ADDED
@@ -0,0 +1,219 @@
1
+ /**
2
+ * @class ExtMVC.App
3
+ * @extends Ext.util.Observable
4
+ * @cfg {Boolean} usesHistory True to automatically create required DOM elements for Ext.History,
5
+ * sets up a listener on Ext.History's change event to fire this.onHistoryChange. False by default
6
+ */
7
+ ExtMVC.App = Ext.extend(Ext.util.Observable, {
8
+ /**
9
+ * @constructor
10
+ * Sets up the Application - adds events, sets up namespaces, optionally sets up history.
11
+ * Fires the 'before-launch' event before initializing router, viewport and history.
12
+ * Calls this.launch() once everything else is set up (override the 'launch' method to provide your own logic).
13
+ * Fires the 'launched' event after calling this.launch()
14
+ */
15
+ constructor: function(config) {
16
+ ExtMVC.App.superclass.constructor.apply(this, arguments);
17
+
18
+ //apply configuration object and set up namespaces
19
+ Ext.apply(this, config || {});
20
+ window[this.name] = this;
21
+
22
+ this.initializeNamespaces();
23
+
24
+ // Ext.onReady(this.onReady, this);
25
+
26
+ this.on('launched', function() {
27
+ /**
28
+ * TODO: This used to reside in initializeHistory but this.launch() needs to be
29
+ * called before this dispatches so it is temporarily here... ugly though
30
+ */
31
+ if (this.usesHistory) {
32
+ if (this.dispatchHistoryOnLoad === true) {
33
+ Ext.History.init(function(history) {
34
+ var hash = document.location.hash.replace("#", "");
35
+ var params = this.router.recognise(hash);
36
+
37
+ if (params) {this.dispatch(params);}
38
+ }, this);
39
+ } else {
40
+ Ext.History.init();
41
+ }
42
+ }
43
+ }, this);
44
+ },
45
+
46
+ /**
47
+ * @private
48
+ * Called when Ext.onReady fires
49
+ */
50
+ onReady: function() {
51
+ if (this.fireEvent('before-launch', this)) {
52
+ this.initializeRouter();
53
+ // this.initializeViewport();
54
+ this.initializeEvents();
55
+
56
+ if (this.usesHistory === true) this.initializeHistory();
57
+
58
+ this.launch();
59
+ }
60
+ },
61
+
62
+ /**
63
+ * @property name
64
+ * @type String
65
+ * The application's name. This is used when creating namespaces for models, views and controllers,
66
+ * and automatically set up as a global variable reference to this application. Read only.
67
+ */
68
+ name: 'MyApp',
69
+
70
+ /**
71
+ * @property usesHistory
72
+ * @type Boolean
73
+ * True to automatically create required DOM elements for Ext.History,
74
+ * sets up a listener on Ext.History's change event to fire this.onHistoryChange.
75
+ * False by default
76
+ */
77
+ usesHistory: false,
78
+
79
+ /**
80
+ * @prop dispatchHistoryOnLoad
81
+ * @type Boolean
82
+ * If usesHistory is true and dispatchHistoryOnLoad is also true, the OS will attempt to match
83
+ * any string currently after the # in the url and dispatch to it
84
+ */
85
+ dispatchHistoryOnLoad: true,
86
+
87
+ /**
88
+ * Called when the application is booted up. Override this to provide your own startup logic (defaults to Ext.emptyFn)
89
+ */
90
+ launch: function() {
91
+ this.fireEvent('launched', this);
92
+ },
93
+
94
+ /**
95
+ * @property params
96
+ * @type Object
97
+ * An object containing the most current parameters (usually decoded from a url using this.router)
98
+ * e.g. {controller: 'index', action: 'welcome', id: 10}
99
+ */
100
+ params: {},
101
+
102
+ /**
103
+ * Dispatches a request to a registered controller.
104
+ * @param {Object} dispatchConfig A config object which should look something like this:
105
+ * {controller: 'MyController', action: 'index'}, where 'MyController' is the key for a controller
106
+ * which has been registered to the controller. If action is not specified, it defaults to 'index'
107
+ * @param {Object} scope The scope in which to fire the event (defaults to the controller)
108
+ * @param {Array} args An array of arguments which are passed to the controller action.
109
+ */
110
+ dispatch: function dispatch(dispatchConfig, scope, args) {
111
+ var dispatchConfig = dispatchConfig || {};
112
+ Ext.applyIf(dispatchConfig, {
113
+ action: 'index'
114
+ });
115
+
116
+ this.params = dispatchConfig;
117
+
118
+ var c = ExtMVC.getController(dispatchConfig.controller);
119
+ if (c != undefined) {
120
+ var action = c[dispatchConfig.action];
121
+
122
+ if (typeof action == "function") action.apply(scope || c, args || []);
123
+ else throw new Error(String.format("Action '{0}' not found on Controller '{1}'", dispatchConfig.action, dispatchConfig.controller));
124
+ }
125
+ },
126
+
127
+ /**
128
+ * Sets up a Router instance. This is called automatically before onLaunch()
129
+ * Add routes using this.router.connect
130
+ */
131
+ initializeRouter: function() {
132
+ if (this.router == undefined) {
133
+ this.router = new ExtMVC.router.Router();
134
+ ExtMVC.router.Router.defineRoutes(this.router);
135
+ }
136
+ },
137
+
138
+ /**
139
+ * Uses Ext.namespace to create packages view controllers, models and views
140
+ * E.g. if name = 'Blog' or this.name = 'Blog', this is the same as:
141
+ * Ext.ns('Blog', 'Blog.controllers', 'Blog.models', 'Blog.views')
142
+ */
143
+ initializeNamespaces: function initializeNamespaces(name) {
144
+ var name = name || this.name;
145
+ if (name) {
146
+ Ext.ns(name, name + '.controllers', name + '.models', name + '.views');
147
+ };
148
+ },
149
+
150
+ /**
151
+ * Creates the necessary DOM elements required for Ext.History to manage state
152
+ * Sets up listeners on Ext.History's change event to fire the dispatch() action in the normal way.
153
+ * This is not called automatically as not all applications will need it
154
+ */
155
+ initializeHistory: function initializeHistory() {
156
+ this.historyForm = Ext.getBody().createChild({
157
+ tag: 'form',
158
+ action: '#',
159
+ cls: 'x-hidden',
160
+ id: 'history-form',
161
+ children: [
162
+ {
163
+ tag: 'div',
164
+ children: [
165
+ {
166
+ tag: 'input',
167
+ id: 'x-history-field',
168
+ type: 'hidden'
169
+ },
170
+ {
171
+ tag: 'iframe',
172
+ id: 'x-history-frame'
173
+ }
174
+ ]
175
+ }
176
+ ]
177
+ });
178
+
179
+ Ext.History.on('change', this.onHistoryChange, this);
180
+ },
181
+
182
+ /**
183
+ * Takes a history token (anything after the # in the url), consults the router and dispatches
184
+ * to the appropriate controller and action if a match was found
185
+ * @param {String} token The url token (e.g. the token would be cont/act/id for a url like mydomain.com/#cont/act/id)
186
+ */
187
+ onHistoryChange: function onHistoryChange(token) {
188
+ var match = this.router.recognise(token);
189
+
190
+ if (match) {
191
+ this.dispatch(match, null, [{url: token}]);
192
+ };
193
+ },
194
+
195
+ /**
196
+ * Sets up events emitted by the Application
197
+ */
198
+ initializeEvents: function initializeEvents() {
199
+ this.addEvents(
200
+ /**
201
+ * @event before-launch
202
+ * Fires before this application launches
203
+ * @param {ExtMVC.App} this The application about to be launched
204
+ */
205
+ 'before-launch',
206
+
207
+ /**
208
+ * @event launched
209
+ * Fires once the application has been launched
210
+ * @param {ExtMVC.App} this The application which has been launched
211
+ */
212
+ 'launched'
213
+ );
214
+ }
215
+ });
216
+
217
+ ExtMVC.App.define = function(config) {
218
+ ExtMVC.app = new ExtMVC.App(config);
219
+ };
data/lib/js/MVC.js ADDED
@@ -0,0 +1,260 @@
1
+ /**
2
+ * @class ExtMVC
3
+ * ExtMVC
4
+ * @singleton
5
+ */
6
+ ExtMVC = Ext.extend(Ext.util.Observable, {
7
+ version: "0.7a",
8
+
9
+ constructor: function() {
10
+ ExtMVC.superclass.constructor.apply(this, arguments);
11
+
12
+ /**
13
+ * @property dispatcher
14
+ * @type Ext.lib.Dispatcher
15
+ * The dispatcher object which finds the right controller and action when ExtMVC.dispatch is called
16
+ */
17
+ // this.dispatcher = new Ext.lib.Dispatcher({
18
+ //
19
+ // });
20
+ },
21
+
22
+ dispatch: function() {
23
+ var dispatcher = this.dispatcher;
24
+
25
+ return dispatcher.dispatch.apply(dispatcher, arguments);
26
+ },
27
+
28
+ /**
29
+ * Sets the Ext.Application instance currently in use. This is currently required :/
30
+ * @param {Ext.Application} app The application currently in use
31
+ */
32
+ setApplication: function(app) {
33
+ this.app = app;
34
+ this.name = app.name;
35
+
36
+ ExtMVC.model.modelNamespace = window[app.name].models;
37
+ },
38
+
39
+ fields: {
40
+
41
+ },
42
+
43
+ registerFields: function(name, fields) {
44
+ this.fields[name] = fields;
45
+ },
46
+
47
+ getFields: function(name) {
48
+ return this.fields[name];
49
+ },
50
+
51
+
52
+
53
+ /**
54
+ * Registers a model class with Ext MVC
55
+ * @param {String} name The name to give this model
56
+ * @param {Object} config Model definition configuration
57
+ */
58
+ registerModel: function(name, config) {
59
+ this.registerClass('model', arguments);
60
+ },
61
+
62
+ /**
63
+ * Registers a controller class with Ext MVC
64
+ * @param {String} name The name to give this controller
65
+ * @param {Object} config Controller definition configuration
66
+ */
67
+ registerController: function(name, config) {
68
+ this.registerClass('controller', arguments);
69
+ },
70
+
71
+ /**
72
+ * Registers a view class with Ext MVC.
73
+ * @param {String} namesapce The namespace to add this view to
74
+ * @param {String} name The name to give this view
75
+ * @param {Object} config View definition configuration
76
+ */
77
+ registerView: function(namespace, name, config) {
78
+ this.registerClass('view', arguments);
79
+ },
80
+
81
+ /**
82
+ * Abstraction for registering views, models and controllers
83
+ * @param {String} managerName The name of the class manager to register with
84
+ * @param {Array} args The args to pass to the manager's register method
85
+ */
86
+ registerClass: function(managerName, args) {
87
+ var manager = this.getClassManager(managerName);
88
+
89
+ manager.register.apply(manager, args);
90
+ },
91
+
92
+ /**
93
+ * @property classManagers
94
+ * @type Object
95
+ * {name: classManager} mappings used by this.getClassManager and this.registerClassManager
96
+ */
97
+ classManagers: {},
98
+
99
+ /**
100
+ * @private
101
+ * Sets up model, view and controller class managers
102
+ */
103
+ initializeClassManagers: function() {
104
+ this.registerClassManager('model', new ExtMVC.lib.ModelClassManager());
105
+ this.registerClassManager('view', new ExtMVC.lib.ViewClassManager());
106
+ this.registerClassManager('controller', new ExtMVC.lib.ControllerClassManager());
107
+ },
108
+
109
+ /**
110
+ * Returns the class manager for the given name
111
+ * @param {String} name The name of the manager (model, view or controller)
112
+ * @return {ExtMVC.lib.ClassManager} The class manager instance
113
+ */
114
+ getClassManager: function(name) {
115
+ return this.classManagers[name];
116
+ },
117
+
118
+ /**
119
+ * Registers a class manager instance under a given name
120
+ * @param {String} name The name of the class manager
121
+ * @param {ExtMVC.lib.ClassManager} manager The ClassManager instance to register
122
+ */
123
+ registerClassManager: function(name, manager) {
124
+ this.classManagers[name] = manager;
125
+ },
126
+
127
+ /**
128
+ * Returns the canonical controller instance for the given controller name
129
+ * @return {ExtMVC.Controller} The controller instance
130
+ */
131
+ getController: function(name) {
132
+ return this.getClassManager('controller').getInstance(name);
133
+ },
134
+
135
+ /**
136
+ * Returns the constructor for a given model name
137
+ * @param {String} name The name of the model
138
+ * @return {Function} The model constructor
139
+ */
140
+ getModel: function(name) {
141
+ return this.getClassManager('model').getConstructor(name);
142
+ },
143
+
144
+ /**
145
+ * Instantiates a model of the given name with the data supplied
146
+ * @param {String} modelName The name of the model to instantiate
147
+ * @param {Object} data Data object to instantiate the instance with
148
+ * @return {ExtMVC.Model} The new model instance
149
+ */
150
+ buildModel: function(modelName, data) {
151
+ return new (this.getModel(modelName))(data);
152
+ },
153
+
154
+ /**
155
+ * Returns the constructor for a given view namespace/name combination
156
+ * @param {String} namespace The view namespace to look in
157
+ * @param {String} name The name of the view within the view namespace
158
+ * @return {Function} The view constructor
159
+ */
160
+ getView: function getView(namespace, name) {
161
+ return this.getClassManager('view').getConstructor(namespace, name);
162
+ },
163
+
164
+ /**
165
+ * Returns a new view instance for the given namespace/name combo, using the supplied config
166
+ * @param {String} namespace The namespace to find the view from
167
+ * @param {String} name The view name
168
+ * @param {Object} config Optional config object
169
+ * @return {Ext.Component} The new view instance
170
+ */
171
+ buildView: function buildView(namespace, name, config) {
172
+ var constructor = this.getView(namespace, name);
173
+
174
+ return new (constructor)(config);
175
+ },
176
+
177
+ /**
178
+ * Loads packaged classes from a given url, calling a callback when they have been registered. Sample return:
179
+ <pre>
180
+ {
181
+ controllers: [
182
+ {
183
+ name: 'comments',
184
+ superclass: 'crud',
185
+ config: {
186
+ index: function() {
187
+ this.render('index', {
188
+ title: "Loaded on demand!"
189
+ });
190
+ }
191
+ }
192
+ }
193
+ ],
194
+ views: [
195
+ {
196
+ name: 'new',
197
+ namespace: 'comments',
198
+ config: {
199
+ xtype: 'scaffoldnew',
200
+ title: "New Comment"
201
+ }
202
+ }
203
+ ],
204
+ models: [
205
+ {
206
+ name : 'Comment',
207
+ config: {
208
+ fields: [
209
+ {name: 'id', type: 'int'},
210
+ {name: 'title', type: 'string'},
211
+ {name: 'message', type: 'string'}
212
+ ]
213
+ }
214
+ }
215
+ ]
216
+ }
217
+ </pre>
218
+ * @param {String} url The url to retrieve the package from
219
+ * @param {Function} callback Optional callback function, called after the package has been read and registered
220
+ * @param {Object} scope The scope to execute the callback function in
221
+ */
222
+ loadOnDemand: function(url, callback, scope) {
223
+ Ext.Ajax.request({
224
+ url : url,
225
+ scope : scope || this,
226
+ success: function(response) {
227
+ var pkg = Ext.decode(response.responseText);
228
+
229
+ Ext.each(pkg.controllers || [], function(config) {
230
+ this.registerController(config.name, config);
231
+ }, this);
232
+
233
+ Ext.each(pkg.models || [], function(config) {
234
+ this.registerModel(config.name, config);
235
+ }, this);
236
+
237
+ Ext.each(pkg.views || [], function(config) {
238
+ this.registerView(config.namespace, config.name, config);
239
+ }, this);
240
+
241
+ if (Ext.isFunction(callback)) callback.call(scope, pkg);
242
+ }
243
+ });
244
+ }
245
+ });
246
+
247
+ ExtMVC = new ExtMVC();
248
+
249
+ // ExtMVC.initializeClassManagers();
250
+
251
+ Ext.onReady(function() {
252
+ /**
253
+ * @property dispatcher
254
+ * @type Ext.lib.Dispatcher
255
+ * The dispatcher object which finds the right controller and action when ExtMVC.dispatch is called
256
+ */
257
+ ExtMVC.dispatcher = new ExtMVC.lib.Dispatcher();
258
+ });
259
+
260
+ Ext.ns('ExtMVC.router', 'ExtMVC.plugin', 'ExtMVC.controller', 'ExtMVC.view', 'ExtMVC.view.scaffold', 'ExtMVC.lib', 'ExtMVC.test');
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @class ExtMVC.Presenter
3
+ * @extends Ext.util.Observable
4
+ * Used as an interface between a controller and its views
5
+ */
6
+ ExtMVC.Presenter = Ext.extend(Ext.util.Observable, {
7
+
8
+ constructor: function(config) {
9
+ ExtMVC.Presenter.superclass.constructor.apply(this, arguments);
10
+
11
+ this.addEvents(
12
+ /**
13
+ * @event load
14
+ * Fires when all items in the Presenter have been loaded
15
+ */
16
+ 'load'
17
+ );
18
+
19
+ /**
20
+ * @property loaded
21
+ * @type Boolean
22
+ * True if all items that must be loaded before rendering have been
23
+ */
24
+ this.loaded = false;
25
+
26
+ /**
27
+ * @property loading
28
+ * @type Boolean
29
+ * True while the loader is loading
30
+ */
31
+ this.loading = false;
32
+ },
33
+
34
+ load: function() {
35
+ if (this.loaded || this.loading) return;
36
+
37
+ this.each(function(item, index, length) {
38
+ var callback = function(index) {
39
+ return function() {
40
+ if (index == length) {
41
+ this.loaded = true;
42
+ this.loading = false;
43
+
44
+ this.fireEvent('load');
45
+ }
46
+ };
47
+ }(index);
48
+
49
+ item.on('load', callback, this, {single: true});
50
+ }, this);
51
+ }
52
+ });