eyeballs 0.3.7 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }