eyeballs 0.3.7 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/CHANGELOG +6 -0
  2. data/Gemfile +13 -0
  3. data/Gemfile.lock +47 -0
  4. data/README.md +62 -17
  5. data/Rakefile +1 -1
  6. data/dist/{jquery-1.4.2.min.js → jquery/jquery-1.4.2.min.js} +0 -0
  7. data/dist/jquery/jquery.ba-hashchange.js +244 -0
  8. data/dist/{jquery.livequery.js → jquery/jquery.livequery.js} +0 -0
  9. data/dist/{mustache.js → mustache/mustache.0.2.3.js} +27 -50
  10. data/eyeballs.gemspec +23 -14
  11. data/lib/eyeballs/app_generator.rb +3 -3
  12. data/spec/app_generator_spec.rb +7 -1
  13. data/spec/spec_helper.rb +1 -2
  14. data/src/{o_O.localstorage.js → adapters/o_O.localstorage.js} +0 -0
  15. data/src/{jquery.o_O.couchdb.js → drivers/jquery/adapters/o_O.couchdb.js} +0 -0
  16. data/src/{jquery.o_O.dom.js → drivers/jquery/adapters/o_O.dom.js} +0 -0
  17. data/src/{jquery.o_O.rails.js → drivers/jquery/adapters/o_O.rest.js} +1 -1
  18. data/src/{jquery.o_O.js → drivers/jquery/modules/o_O.controller.js} +3 -65
  19. data/src/drivers/jquery/modules/o_O.routes.js +45 -0
  20. data/src/drivers/jquery/modules/o_O.support.js +69 -0
  21. data/src/modules/o_O.model.js +188 -0
  22. data/src/modules/o_O.validations.js +45 -0
  23. data/src/o_O.js +0 -235
  24. data/templates/app_root/config/initializer.js +3 -0
  25. data/templates/app_root/config/routes.js +7 -0
  26. data/test/unit/test_controller.html +7 -7
  27. data/test/unit/test_dom.html +7 -4
  28. data/test/unit/test_dom_with_callbacks.html +7 -3
  29. data/test/unit/test_form.html +7 -2
  30. data/test/unit/test_localstorage.html +7 -4
  31. data/test/unit/test_model.html +7 -3
  32. data/test/unit/test_model_with_callbacks.html +7 -3
  33. data/test/unit/{test_rails.html → test_rest.html} +9 -6
  34. data/test/unit/test_routing.html +76 -0
  35. metadata +39 -15
  36. data/eyeballs.js.gemspec +0 -83
@@ -1,7 +1,12 @@
1
1
  /*
2
- mustache.js Logic-less templates in JavaScript
2
+ Shameless port of http://github.com/defunkt/mustache
3
+ by Jan Lehnardt <jan@apache.org>,
4
+ Alexander Lang <alex@upstream-berlin.com>,
5
+ Sebastian Cohnen <sebastian.cohnen@googlemail.com>
3
6
 
4
- See http://mustache.github.com/ for more info.
7
+ Thanks @defunkt for the awesome code.
8
+
9
+ See http://github.com/defunkt/mustache for more info.
5
10
  */
6
11
 
7
12
  var Mustache = function() {
@@ -17,12 +22,8 @@ var Mustache = function() {
17
22
  },
18
23
 
19
24
  render: function(template, context, partials, in_recursion) {
20
- // reset buffer
21
- // TODO: make this non-lazy
22
- if(!in_recursion)
23
- this.buffer = [];
24
25
  // fail fast
25
- if(!this.includes("", template)) {
26
+ if(template.indexOf(this.otag) == -1) {
26
27
  if(in_recursion) {
27
28
  return template;
28
29
  } else {
@@ -58,7 +59,7 @@ var Mustache = function() {
58
59
  */
59
60
  render_pragmas: function(template) {
60
61
  // no pragmas
61
- if(!this.includes("%", template)) {
62
+ if(template.indexOf(this.otag + "%") == -1) {
62
63
  return template;
63
64
  }
64
65
 
@@ -94,48 +95,29 @@ var Mustache = function() {
94
95
  },
95
96
 
96
97
  /*
97
- Renders inverted (^) and normal (#) sections
98
+ Renders boolean and enumerable sections
98
99
  */
99
100
  render_section: function(template, context, partials) {
100
- if(!this.includes("#", template) && !this.includes("^", template)) {
101
+ if(template.indexOf(this.otag + "#") == -1) {
101
102
  return template;
102
103
  }
103
-
104
104
  var that = this;
105
105
  // CSW - Added "+?" so it finds the tighest bound, not the widest
106
- var regex = new RegExp(this.otag + "(\\^|\\#)(.+)" + this.ctag +
107
- "\\s*([\\s\\S]+?)" + this.otag + "\\/\\2" + this.ctag +
108
- "\\s*", "mg");
106
+ var regex = new RegExp(this.otag + "\\#(.+)" + this.ctag +
107
+ "\\s*([\\s\\S]+?)" + this.otag + "\\/\\1" + this.ctag + "\\s*", "mg");
109
108
 
110
109
  // for each {{#foo}}{{/foo}} section do...
111
- return template.replace(regex, function(match, type, name, content) {
110
+ return template.replace(regex, function(match, name, content) {
112
111
  var value = that.find(name, context);
113
- if(type == "^") { // inverted section
114
- if(!value || that.is_array(value) && value.length == 0) {
115
- // false or empty list, render it
116
- return that.render(content, context, partials, true);
117
- } else {
118
- return "";
119
- }
120
- } else if(type == "#") { // normal section
121
- if(that.is_array(value)) { // Enumerable, Let's loop!
122
- return that.map(value, function(row) {
123
- return that.render(content, that.merge(context,
124
- that.create_context(row)), partials, true);
125
- }).join("");
126
- } else if(that.is_object(value)) { // Object, Use it as subcontext!
127
- return that.render(content,
128
- that.merge(context, that.create_context(value)), partials, true);
129
- } else if(typeof value === "function") {
130
- // higher order section
131
- return value.call(context, content, function(text) {
132
- return that.render(text, context, partials, true);
133
- })
134
- } else if(value) { // boolean section
135
- return that.render(content, context, partials, true);
136
- } else {
137
- return "";
138
- }
112
+ if(that.is_array(value)) { // Enumerable, Let's loop!
113
+ return that.map(value, function(row) {
114
+ return that.render(content, that.merge(context,
115
+ that.create_context(row)), partials, true);
116
+ }).join("");
117
+ } else if(value) { // boolean section
118
+ return that.render(content, context, partials, true);
119
+ } else {
120
+ return "";
139
121
  }
140
122
  });
141
123
  },
@@ -148,7 +130,7 @@ var Mustache = function() {
148
130
  var that = this;
149
131
 
150
132
  var new_regex = function() {
151
- return new RegExp(that.otag + "(=|!|>|\\{|%)?([^\/#\^]+?)\\1?" +
133
+ return new RegExp(that.otag + "(=|!|>|\\{|%)?([^\/#]+?)\\1?" +
152
134
  that.ctag + "+", "g");
153
135
  };
154
136
 
@@ -158,7 +140,7 @@ var Mustache = function() {
158
140
  lines[i] = lines[i].replace(regex, function(match, operator, name) {
159
141
  switch(operator) {
160
142
  case "!": // ignore comments
161
- return "";
143
+ return match;
162
144
  case "=": // set new delimiters, rebuild the replace regexp
163
145
  that.set_delimiters(name);
164
146
  regex = new_regex();
@@ -219,16 +201,11 @@ var Mustache = function() {
219
201
 
220
202
  // Utility methods
221
203
 
222
- /* includes tag */
223
- includes: function(needle, haystack) {
224
- return haystack.indexOf(this.otag + needle) != -1;
225
- },
226
-
227
204
  /*
228
205
  Does away with nasty characters
229
206
  */
230
207
  escape: function(s) {
231
- return ((s == null) ? "" : s).toString().replace(/&(?!\w+;)|["<>\\]/g, function(s) {
208
+ return ((s == null) ? "" : s).toString().replace(/[&"<>\\]/g, function(s) {
232
209
  switch(s) {
233
210
  case "&": return "&amp;";
234
211
  case "\\": return "\\\\";;
@@ -305,7 +282,7 @@ var Mustache = function() {
305
282
 
306
283
  return({
307
284
  name: "mustache.js",
308
- version: "0.3.0-dev",
285
+ version: "0.2.3",
309
286
 
310
287
  /*
311
288
  Turns a template and view into HTML
data/eyeballs.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{eyeballs}
8
- s.version = "0.3.7"
8
+ s.version = "0.4.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Paul Campbell"]
12
- s.date = %q{2010-07-02}
12
+ s.date = %q{2010-07-06}
13
13
  s.default_executable = %q{eyeballs}
14
14
  s.email = %q{paul@rslw.com}
15
15
  s.executables = ["eyeballs"]
@@ -18,16 +18,18 @@ Gem::Specification.new do |s|
18
18
  ]
19
19
  s.files = [
20
20
  "CHANGELOG",
21
+ "Gemfile",
22
+ "Gemfile.lock",
21
23
  "README.md",
22
24
  "Rakefile",
23
25
  "app.rb",
24
26
  "bin/eyeballs",
25
27
  "config.ru",
26
- "dist/jquery-1.4.2.min.js",
27
- "dist/jquery.livequery.js",
28
- "dist/mustache.js",
28
+ "dist/jquery/jquery-1.4.2.min.js",
29
+ "dist/jquery/jquery.ba-hashchange.js",
30
+ "dist/jquery/jquery.livequery.js",
31
+ "dist/mustache/mustache.0.2.3.js",
29
32
  "eyeballs.gemspec",
30
- "eyeballs.js.gemspec",
31
33
  "lib/eyeballs.rb",
32
34
  "lib/eyeballs/app_detector.rb",
33
35
  "lib/eyeballs/app_generator.rb",
@@ -35,12 +37,18 @@ Gem::Specification.new do |s|
35
37
  "lib/eyeballs/controller_generator.rb",
36
38
  "lib/eyeballs/model_generator.rb",
37
39
  "lib/eyeballs/scaffold_generator.rb",
38
- "src/jquery.o_O.couchdb.js",
39
- "src/jquery.o_O.dom.js",
40
- "src/jquery.o_O.js",
41
- "src/jquery.o_O.rails.js",
40
+ "src/adapters/o_O.localstorage.js",
41
+ "src/drivers/jquery/adapters/o_O.couchdb.js",
42
+ "src/drivers/jquery/adapters/o_O.dom.js",
43
+ "src/drivers/jquery/adapters/o_O.rest.js",
44
+ "src/drivers/jquery/modules/o_O.controller.js",
45
+ "src/drivers/jquery/modules/o_O.routes.js",
46
+ "src/drivers/jquery/modules/o_O.support.js",
47
+ "src/modules/o_O.model.js",
48
+ "src/modules/o_O.validations.js",
42
49
  "src/o_O.js",
43
- "src/o_O.localstorage.js",
50
+ "templates/app_root/config/initializer.js",
51
+ "templates/app_root/config/routes.js",
44
52
  "templates/app_root/index.html",
45
53
  "templates/controller.js",
46
54
  "templates/model.js",
@@ -58,12 +66,13 @@ Gem::Specification.new do |s|
58
66
  "test/unit/test_localstorage.html",
59
67
  "test/unit/test_model.html",
60
68
  "test/unit/test_model_with_callbacks.html",
61
- "test/unit/test_rails.html"
69
+ "test/unit/test_rest.html",
70
+ "test/unit/test_routing.html"
62
71
  ]
63
72
  s.homepage = %q{http://www.github.com/paulca/eyeballs.js}
64
73
  s.rdoc_options = ["--charset=UTF-8"]
65
74
  s.require_paths = ["lib"]
66
- s.rubygems_version = %q{1.3.6}
75
+ s.rubygems_version = %q{1.3.7}
67
76
  s.summary = %q{A lightweight javascript MVC framework.}
68
77
  s.test_files = [
69
78
  "spec/app_generator_spec.rb",
@@ -78,7 +87,7 @@ Gem::Specification.new do |s|
78
87
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
79
88
  s.specification_version = 3
80
89
 
81
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
90
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
82
91
  s.add_runtime_dependency(%q<thor>, [">= 0"])
83
92
  s.add_runtime_dependency(%q<activesupport>, [">= 0"])
84
93
  else
@@ -17,9 +17,9 @@ module Eyeballs
17
17
 
18
18
  def build_the_app
19
19
  directory "templates/app_root", new_app_path
20
- copy_file 'dist/jquery-1.4.2.min.js', "#{new_app_path}/vendor/jquery/jquery-1.4.2.min.js"
21
- copy_file 'dist/jquery.livequery.js', "#{new_app_path}/vendor/jquery/jquery.livequery.js"
22
- copy_file 'dist/mustache.js', "#{new_app_path}/vendor/mustache/mustache.js"
20
+ copy_file 'dist/jquery/jquery-1.4.2.min.js', "#{new_app_path}/vendor/jquery/jquery-1.4.2.min.js"
21
+ copy_file 'dist/jquery/jquery.livequery.js', "#{new_app_path}/vendor/jquery/jquery.livequery.js"
22
+ copy_file 'dist/mustache/mustache.0.2.3.js', "#{new_app_path}/vendor/mustache/mustache.0.2.3.js"
23
23
  directory "src", "#{new_app_path}/vendor/eyeballs/"
24
24
  end
25
25
 
@@ -12,6 +12,7 @@ describe Eyeballs::AppGenerator do
12
12
  let(:model_dir) { file('test', 'app', 'models') }
13
13
  let(:controller_dir) { file('test', 'app', 'controllers') }
14
14
  let(:view_dir) { file('test', 'app', 'views') }
15
+ let(:config_dir) { file('test', 'config') }
15
16
  let(:vendor_dir) { file('test', 'vendor') }
16
17
  let(:jquery_dir) { file('test', 'vendor', 'jquery') }
17
18
  let(:eyeballs_dir) { file('test', 'vendor', 'eyeballs') }
@@ -19,8 +20,10 @@ describe Eyeballs::AppGenerator do
19
20
 
20
21
  let(:jquery_file) { file('test', 'vendor', 'jquery', 'jquery-1.4.2.min.js') }
21
22
  let(:livequery_file) { file('test', 'vendor', 'jquery', 'jquery.livequery.js') }
22
- let(:mustache_file) { file('test', 'vendor', 'mustache', 'mustache.js') }
23
+ let(:mustache_file) { file('test', 'vendor', 'mustache', 'mustache.0.2.3.js') }
23
24
  let(:index_file) { file('test', 'index.html') }
25
+ let(:initializer_file) { file('test', 'config', 'initializer.js')}
26
+ let(:routes_file) { file('test', 'config', 'routes.js')}
24
27
 
25
28
  it "should create the test root" do
26
29
  File.exists?(test_root).should be_true
@@ -31,6 +34,7 @@ describe Eyeballs::AppGenerator do
31
34
  model_dir.should exist
32
35
  controller_dir.should exist
33
36
  view_dir.should exist
37
+ config_dir.should exist
34
38
  vendor_dir.should exist
35
39
  jquery_dir.should exist
36
40
  eyeballs_dir.should exist
@@ -42,6 +46,8 @@ describe Eyeballs::AppGenerator do
42
46
  livequery_file.should exist
43
47
  mustache_file.should exist
44
48
  index_file.should exist
49
+ initializer_file.should exist
50
+ routes_file.should exist
45
51
  end
46
52
 
47
53
  after(:all) do
data/spec/spec_helper.rb CHANGED
@@ -1,8 +1,7 @@
1
1
  require 'eyeballs'
2
2
  require 'fileutils'
3
- require 'ruby-debug'
4
3
  require 'pathname'
5
- Debugger.settings[:autoeval] = true
4
+ # Debugger.settings[:autoeval] = true
6
5
 
7
6
  def create_test_root
8
7
  FileUtils.mkdir_p(test_root)
@@ -1,5 +1,5 @@
1
1
  // REST & Rails, woop!
2
- o_O.rails = {
2
+ o_O.rest = {
3
3
  all: function(model, callback){
4
4
  $.get('/' + model.table_name, function(response){
5
5
  var documents = JSON.parse(response);
@@ -12,6 +12,7 @@ o_O.controller = {
12
12
  var controller = controller;
13
13
 
14
14
  $(function(){
15
+
15
16
  for(var action in controller)
16
17
  {
17
18
  var selector = '[data-controller=' + controller_name + '][data-action=' + action + ']';
@@ -25,13 +26,13 @@ o_O.controller = {
25
26
  })
26
27
  }
27
28
  $('[data-bind]').livequery(function(){
28
- var binders = $(this).attr('data-bind').match(/[\+]?(\s+)?[^ :]?[: ]?[^ \/]+[ \/]+[^ ;]+[ ;]?/g)
29
+ var binders = $(this).attr('data-bind').match(/[\+]?(\s+)?[^ :]?[: ]?[^ #]+[ #]+[^ ;]+[ ;]?/g)
29
30
  if(binders != null && binders.length > 0)
30
31
  {
31
32
  for(i = 0; i < binders.length; i++)
32
33
  {
33
34
  var rule = binders[i];
34
- var parts = rule.match(/([\+])?(\s+)?(([^ :]+)([: ]+))?([^ \/]+)[ \/]+([^ ;]+)[ ;]?/)
35
+ var parts = rule.match(/([\+])?(\s+)?(([^ :]+)([: ]+))?([^ #]+)[ #]+([^ ;]+)[ ;]?/)
35
36
  var default_bit = parts[1];
36
37
  var this_action_event = parts[4];
37
38
  if(this_action_event === undefined)
@@ -54,67 +55,4 @@ o_O.controller = {
54
55
  });
55
56
  return controller;
56
57
  }
57
- }
58
-
59
- o_O.find_attributes = function(template, callback){
60
- var object = {};
61
- for(i = 0; i<template.find('[data-attribute]').length; i++)
62
- {
63
- field = $(template.find('[data-attribute]')[i]);
64
- object[field.attr('data-attribute')] = callback(field);
65
- }
66
- return object;
67
- }
68
-
69
- o_O.params = function(form){
70
- return o_O.find_attributes(form, function(field){
71
- if(field.is('[type=radio]'))
72
- {
73
- return $('[data-attribute=' + field.attr('data-attribute') + ']:checked').val()
74
- }
75
- else
76
- {
77
- return field.val();
78
- }
79
- });
80
- }
81
-
82
- o_O.render = function(template, data, options){
83
- o_O.get_template(template, data, function(data, template){
84
- var rendered = Mustache.to_html(template, data);
85
- if(typeof options === 'object')
86
- {
87
- if(options.append)
88
- {
89
- $(options.append).append(rendered);
90
- }
91
- if(options.prepend)
92
- {
93
- $(options.prepend).prepend(rendered);
94
- }
95
- }
96
- });
97
- }
98
-
99
- o_O.get_template = function(template, data, callback){
100
- if(o_O.templates[template])
101
- {
102
- callback(data, o_O.templates[template]);
103
- }
104
- else
105
- {
106
- var url;
107
- if(o_O.config.template_path)
108
- {
109
- url = o_O.config.template_path + '/';
110
- }
111
- else
112
- {
113
- url = 'app/views/'
114
- }
115
- $.get(url + template + '.html.mustache', function(response){
116
- o_O.templates[template] = response;
117
- callback(data, response);
118
- });
119
- }
120
58
  }
@@ -0,0 +1,45 @@
1
+ o_O.routes = {
2
+
3
+ rules: {},
4
+ urls: [],
5
+
6
+ router: {
7
+ match: function(route, options){
8
+
9
+ var figure_action = function(options){
10
+ var parts = options.to.split('#');
11
+ var controller = parts[0];
12
+ var action = parts[1];
13
+
14
+ controller = controller.capitalize() + "Controller";
15
+ return window[controller][action];
16
+ }
17
+
18
+ o_O.routes.rules[route] = {"action": figure_action(options), "with": options.with};
19
+ o_O.routes.urls.push(route);
20
+ }
21
+ },
22
+
23
+ draw: function(callback){
24
+ $(function(){
25
+
26
+ callback(o_O.routes.router);
27
+
28
+ $(window).bind( 'hashchange', function(){
29
+ var hash = location.hash.replace(/^(#)/, '');
30
+ if(o_O.routes.urls.indexOf(hash) >= 0)
31
+ {
32
+ o_O.routes.rules[hash].action(o_O.routes.rules[hash].with);
33
+ }
34
+ });
35
+
36
+ $('a').live('click', function(){
37
+ if($(this).is('a[data-ajax-history=true]'))
38
+ {
39
+ document.location.hash = $(this).attr('href')
40
+ return false;
41
+ }
42
+ });
43
+ })
44
+ }
45
+ }
@@ -0,0 +1,69 @@
1
+ o_O.find_attributes = function(template, callback){
2
+ var object = {};
3
+ for(i = 0; i<template.find('[data-attribute]').length; i++)
4
+ {
5
+ field = $(template.find('[data-attribute]')[i]);
6
+ object[field.attr('data-attribute')] = callback(field);
7
+ }
8
+ return object;
9
+ }
10
+
11
+ o_O.params = function(form){
12
+ return o_O.find_attributes(form, function(field){
13
+ if(field.is('[type=radio]'))
14
+ {
15
+ return $('[data-attribute=' + field.attr('data-attribute') + ']:checked').val()
16
+ }
17
+ else
18
+ {
19
+ return field.val();
20
+ }
21
+ });
22
+ }
23
+
24
+ o_O.render = function(template, data, options){
25
+ o_O.get_template(template, data, function(data, template){
26
+ var rendered = Mustache.to_html(template, data);
27
+ if(typeof options === 'object')
28
+ {
29
+ if(options.append)
30
+ {
31
+ $(options.append).append(rendered);
32
+ }
33
+ if(options.prepend)
34
+ {
35
+ $(options.prepend).prepend(rendered);
36
+ }
37
+ }
38
+ });
39
+ }
40
+
41
+ o_O.get_template = function(template, data, callback){
42
+ if(o_O.templates[template])
43
+ {
44
+ callback(data, o_O.templates[template]);
45
+ }
46
+ else
47
+ {
48
+ var url;
49
+ if(o_O.config.template_path)
50
+ {
51
+ url = o_O.config.template_path + '/';
52
+ }
53
+ else
54
+ {
55
+ url = 'app/views/'
56
+ }
57
+ $.get(url + template + '.html.mustache', function(response){
58
+ o_O.templates[template] = response;
59
+ callback(data, response);
60
+ });
61
+ }
62
+ }
63
+
64
+ if(typeof String.prototype.capitalize == 'undefined')
65
+ {
66
+ String.prototype.capitalize = function(){
67
+ return this.charAt(0).toUpperCase() + this.slice(1);
68
+ }
69
+ }