js2 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ ## Version 0.1.8
2
+ * Adding JS2.Observable module to boostrap
3
+ * Fixed "STR2CSTR" bug when used in Ruby 1.9.x
4
+
1
5
  ## Version 0.1.7
2
6
  * Support for Ruby 1.9.x
3
7
 
data/README.md CHANGED
@@ -1,65 +1,75 @@
1
- * [Features](http://github.com/jeffsu/js2/blob/master/wiki/features.md) (simple documentation)
2
- * [Installation](http://github.com/jeffsu/js2/blob/master/wiki/installation.md)
3
- * [Source Code](http://github.com/jeffsu/js2)
4
-
5
- ## OO Javascript
6
-
7
- For every Javascript developer that has ever wanted to create a library for his/her project, there comes a time when an Object Oriented approach is necessary (or extremely desired). Fortunately, there are a plethora of options to choose from:
1
+ [JS2](http://github.com/jeffsu/js2) - Friendly Cross Browser Object Oriented Javascript
2
+ =======================================================================================
8
3
 
9
- > using prototype (not the framework) and hashes:
10
- > var MyClass = function () {
11
- > this.member1 = "member";
12
- > };
13
- > MyClass.prototype = {
14
- > method1: function () { alert('method1 called'); }
15
- > }
16
- > embedding functions right in the instantiator:
17
- > function MyClass () {
18
- > this.member1 = "member1";
19
- > function method1 () {
20
- > alert("method1 called");
21
- > }
22
- > }
23
- > using jQuery (or any of the js OO frameworks) by passing in hashes:
24
- > var MyClass = Class.create({
25
- > member1: "member1",
26
- > method1: function(){ alert("method1 called") },
27
- > });
28
- Unfortunately, these solutions are dissimilar to Java, Ruby, and C-based languages.
4
+ JS2 is a way to write classes in a more familiar way for programmers who are used to syntax in languages such as: Java, Ruby, C++, etc...
5
+ The main motivation is to provide a clean and a less verbose syntax for creating classes, inheritance and modules in Javascript. JS2 plays
6
+ nicely with most of the popular frameworks including: jQuery and prototype. It also provides some syntactic sugar on the repetative aspects
7
+ of Javascript.
29
8
 
30
- ## JS2 Solution
9
+ Sample Syntax:
10
+ class Rectangle {
11
+ property height;
12
+ property width;
13
+
14
+ function area () {
15
+ return this.height * this.width;
16
+ }
17
+ }
18
+
19
+ class Square extends Rectangle {
20
+ function area () {
21
+ return this.width * this.width;
22
+ }
23
+ }
24
+
25
+ var s = new Square();
31
26
 
32
- JS2 language that is a superset of Javascript and the problem it tries to solve is bringing "natural" OO syntax to Javascript by adding a compilation layer.
27
+ * [Installation](http://github.com/jeffsu/js2/blob/master/wiki/installation.md)
28
+ * [Language Features and Examples](http://github.com/jeffsu/js2/blob/master/wiki/features.md)
29
+ * [Compiler Features](http://github.com/jeffsu/js2/blob/master/wiki/compiler.md)
30
+ * [Source](http://github.com/jeffsu/js2)
33
31
 
34
- So in myClass.js2 one could write:
32
+ Things You need to run JS2
33
+ --------------------------
34
+ * Ruby - language used to parse js2 and generate javascript
35
+ * Ruby Gems - ruby package manager
36
+ * js2
37
+ * RubyInline
38
+ * haml (optional)
35
39
 
36
- class MyClass {
37
- var member1 = "member1";
40
+ Quick Start Guide
41
+ -----------------
42
+ Create a js2 file (foo.js2):
43
+ class Person {
44
+ function speak() {
45
+ alert("Hello! I'm a person!");
46
+ }
38
47
 
39
- function method1 () {
40
- alert("method1 called");
48
+ function walk() {
49
+ alert("Walking!");
41
50
  }
42
51
  }
43
52
 
44
- And after compilation myClass.js (notice the .js extension vs the .js2) would be:
45
-
46
- var MyClass = function () { };
47
- MyClass.prototype = {
48
- member1: "member1",
49
- method1: function () { alert("method1 called"); }
53
+ class Student extends Person {
54
+ function speak() {
55
+ alert("Hello, I'm a student!");
56
+ }
50
57
  }
51
58
 
52
- One of the nice things about this solution is that it allows us to "calculate" things like mixins and inheritance at compile time rather than runtime. This compilation layer opens the doors for features such as:
59
+ var person = new Person();
60
+ var student = new Student();
61
+
62
+ person.speak();
63
+ student.speak();
64
+ person.walk();
65
+ student.walk();
53
66
 
54
- * Inheritance
55
- * Mixins (Ruby's multiple inheritance solution)
56
- * getters and setters
57
- * IoC (Dependency Injection)
58
- * AOP (Aspect Oriented Programming)
59
- * foreach
60
- * currying
61
- * More Features
67
+ Run js2 in the same directory
68
+ js2 compile
62
69
 
63
- ## Inspiration
70
+ You should now see these files in that directory:
71
+ * foo.js2
72
+ * foo.js
73
+ * js2bootstrap.js
64
74
 
65
- HAML, SASS, Ruby, Perl, jQuery, Prototype.js
75
+ Include these js2bootstrap.js and foo.js (make sure js2bootstrap.js is included first) in your html page.
data/Rakefile CHANGED
@@ -2,9 +2,10 @@ require 'rubygems'
2
2
  require 'rake'
3
3
  require 'echoe'
4
4
 
5
- JS2_VERSION = '0.1.7'
5
+ JS2_VERSION = '0.1.8'
6
6
  Echoe.new('js2', JS2_VERSION) do |p|
7
- p.description = ""
7
+ p.summary = "Cross-Browser Object Oriented Javascript Compiler"
8
+ p.description = "Cross-Browser Object Oriented Javascript Compiler"
8
9
  p.url = "http://github.com/jeffsu/js2"
9
10
  p.author = "Jeff Su"
10
11
  p.email = "me@jeffsu.com"
@@ -16,7 +17,7 @@ end
16
17
 
17
18
  namespace :js2 do
18
19
  task :compile do
19
- system("pushd lib/js2/ragel/; ruby helper.rb; ragel -C tokenizer.rl; mv tokenizer.c ../parser/tokenizer.rb")
20
+ system("cd ./lib/js2/ragel/; ruby helper.rb; ragel -C tokenizer.rl; mv tokenizer.c ../parser/tokenizer.rb")
20
21
  end
21
22
 
22
23
  task :install do
data/js2.gemspec CHANGED
@@ -2,13 +2,13 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{js2}
5
- s.version = "0.1.7"
5
+ s.version = "0.1.8"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Jeff Su"]
9
- s.date = %q{2010-10-08}
9
+ s.date = %q{2010-10-21}
10
10
  s.default_executable = %q{js2}
11
- s.description = %q{}
11
+ s.description = %q{Cross-Browser Object Oriented Javascript Compiler}
12
12
  s.email = %q{me@jeffsu.com}
13
13
  s.executables = ["js2"]
14
14
  s.extra_rdoc_files = ["README.md", "CHANGELOG", "bin/js2", "lib/js2.rb", "lib/js2/parser/haml.rb", "lib/js2/parser/haml_engine.rb", "lib/js2/parser/lexer.rb", "lib/js2/parser/tokenizer.rb", "lib/js2/ragel/helper.rb", "lib/js2/ragel/tokenizer.rl", "lib/js2/ragel/tokenizer.rl.erb", "lib/js2/standard/class_node.rb", "lib/js2/standard/factory.rb", "lib/js2/standard/node.rb", "lib/js2/util/compilation.rb", "lib/js2/util/config.rb", "lib/js2/util/exec.rb", "lib/js2/util/file_handler.rb", "lib/js2/util/js2bootstrap.js2", "lib/js2/util/processor.rb", "lib/js2/util/rdoc.rb", "lib/js2/util/sel_decorator.rb", "lib/js2/util/haml_filter.rb", "lib/js2/util/jamis.rb"]
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.require_paths = ["lib"]
19
19
  s.rubyforge_project = %q{js2}
20
20
  s.rubygems_version = %q{1.3.7}
21
- s.summary = %q{}
21
+ s.summary = %q{Cross-Browser Object Oriented Javascript Compiler}
22
22
  s.test_files = ["test/test_js2.rb", "test/test_helper.rb"]
23
23
 
24
24
  if s.respond_to? :specification_version then
@@ -21,7 +21,7 @@ class JS2::Parser::Tokenizer
21
21
  // convert ruby string to char*
22
22
  VALUE r_str = argv[0];
23
23
  int data_length = #{RUBY_VERSION.match(/^1\.8/) ? "RSTRING(r_str)->len" : "RSTRING_LEN(r_str)"};
24
- char* data = STR2CSTR(r_str);
24
+ char* data = StringValuePtr(r_str);
25
25
 
26
26
  int in_class = 0;
27
27
  int in_module = 0;
@@ -2498,7 +2498,7 @@ _resume:
2498
2498
  while ( _nacts-- > 0 ) {
2499
2499
  switch ( *_acts++ ) {
2500
2500
  case 6:
2501
- #line 1 "tokenizer.rl"
2501
+ #line 1 "NONE"
2502
2502
  {ts = p;}
2503
2503
  break;
2504
2504
  #line 2505 "tokenizer.c"
@@ -2592,7 +2592,7 @@ _eof_trans:
2592
2592
  {regexp_start = p;}
2593
2593
  break;
2594
2594
  case 7:
2595
- #line 1 "tokenizer.rl"
2595
+ #line 1 "NONE"
2596
2596
  {te = p+1;}
2597
2597
  break;
2598
2598
  case 8:
@@ -3392,7 +3392,7 @@ _eof_trans:
3392
3392
  }}
3393
3393
  break;
3394
3394
  case 139:
3395
- #line 1 "tokenizer.rl"
3395
+ #line 1 "NONE"
3396
3396
  { switch( act ) {
3397
3397
  case 1:
3398
3398
  {{p = ((te))-1;}
@@ -3495,7 +3495,7 @@ _again:
3495
3495
  while ( _nacts-- > 0 ) {
3496
3496
  switch ( *_acts++ ) {
3497
3497
  case 5:
3498
- #line 1 "tokenizer.rl"
3498
+ #line 1 "NONE"
3499
3499
  {ts = 0;}
3500
3500
  break;
3501
3501
  #line 3502 "tokenizer.c"
@@ -434,8 +434,8 @@ class JS2::Parser::Tokenizer
434
434
  int tokenize (int argc, VALUE *argv, VALUE self) {
435
435
  // convert ruby string to char*
436
436
  VALUE r_str = argv[0];
437
- int data_length = RSTRING(r_str)->len;
438
- char* data = STR2CSTR(r_str);
437
+ int data_length = #{RUBY_VERSION.match(/^1\.8/) ? "RSTRING(r_str)->len" : "RSTRING_LEN(r_str)"};
438
+ char* data = StringValuePtr(r_str);
439
439
 
440
440
  int in_class = 0;
441
441
  int in_module = 0;
@@ -257,7 +257,7 @@ class JS2::Parser::Tokenizer
257
257
  // convert ruby string to char*
258
258
  VALUE r_str = argv[0];
259
259
  int data_length = #{RUBY_VERSION.match(/^1\.8/) ? "RSTRING(r_str)->len" : "RSTRING_LEN(r_str)"};
260
- char* data = STR2CSTR(r_str);
260
+ char* data = StringValuePtr(r_str);
261
261
 
262
262
  int in_class = 0;
263
263
  int in_module = 0;
@@ -399,3 +399,50 @@ class JS2.App.JQuery extends JS2.App {
399
399
  }
400
400
  }
401
401
 
402
+ module JS2.Observable {
403
+ function addListener (namespace, funct) {
404
+ this._initializeObservable(namespace);
405
+
406
+ var id = this._listenerCount++;
407
+ var chain = this._listeners[namespace];
408
+ var index = chain.length;
409
+ var info = [ funct, id, namespace ];
410
+
411
+ this._listenerLookup[id.toString()] = info;
412
+ chain.push(info);
413
+ }
414
+
415
+ function trigger () {
416
+ if (! this._listeners) return;
417
+
418
+ var namespace = arguments[0];
419
+ var chain = this._listeners[namespace];
420
+ if (! chain) return;
421
+
422
+ var args = [];
423
+ for (var i=1; i<arguments.length; i++) {
424
+ args.push(arguments[i]);
425
+ }
426
+
427
+ if (chain) {
428
+ foreach (var ele in chain) {
429
+ ele[0].apply(this, args);
430
+ }
431
+ }
432
+ }
433
+
434
+ private
435
+
436
+ function _initializeObservable (namespace) {
437
+ if (! this._listeners) {
438
+ this._listeners = {};
439
+ this._listenerLookup = {};
440
+ this._listenerCount = 1;
441
+ }
442
+
443
+ if (! this._listeners[namespace]) {
444
+ this._listeners[namespace] = [];
445
+ }
446
+ }
447
+ }
448
+
data/wiki/features.md CHANGED
@@ -1,106 +1,73 @@
1
- ## Object Oriented
2
-
3
- ### Class Definition
4
-
5
- > class Foo {
6
- > function method () {
7
- > }
8
- > }
9
-
10
- ### Inheritance
11
-
12
- > class Vehicle {
13
- > function drive () {
14
- > alert('drive');
15
- > }
16
- > }
17
- >
18
- > class Car extends Vehicle {
19
- > }
20
-
21
- ### Getters and Setters
22
-
23
- > class Duck {
24
- > property color; // adds getColor() and setColor()
25
- > }
26
-
27
- ### Mixins (Ruby's multiple inheritance solution)
28
-
29
- > module Flyable {
30
- > function fly () {
31
- > alert('Flying!');
32
- > }
33
- > }
34
- >
35
- > class Duck {
36
- > include Flyable;
37
- > }
38
-
39
- ### AOP (Aspect Oriented Programming)
40
-
41
- > var me = new Human();
42
- > me.addListener('walk', function () { alert('walking') });
43
-
44
- ### Static Methods
45
-
46
- > class Human {
47
- > static function getCount () {
48
- > return this.count;
49
- > }
50
- > static function create () {
51
- > if (this.count) {
52
- > this.count++;
53
- > } else {
54
- > this.count = 1;
55
- > }
56
- > return new this();
57
- > }
58
- > }
59
-
60
- ## Syntactic Sugar
61
-
62
- ### Currying
63
-
64
- > var nonScoped = [ ... lots of data .. ];
65
- > var submitBtn = new Button();
66
- > var ele = document.getElementById('submitBtn');
67
- > ele.onClick = curry (evt) with (submitBtn) {
68
- > submitBtn.click();
69
- > };
70
-
71
- ### Foreach
72
-
73
- > foreach (var item in array) alert(item);
74
- > foreach (var item:i in array) alert(i + ' is ' + item);
75
- > curry (arg1, arg2) with (scopeVar1, scopeVar2) { };
76
-
77
- ##Other Features
78
-
79
- ### Templating in HAML/SASS (useful for ajax applications)
80
-
81
- > //--- in uiBuilder.js2.haml
82
- > UIBuilder
83
- > button(name)
84
- > %div.button= "#name#"
85
- >
86
- > //--- in uiBuilder.js2
87
- > class UIBuilder {
88
- > function getButton (name) {
89
- > this.htmlCache.button(name);
90
- > }
91
- > }
92
- >
93
- > //--- in page.html
94
- > var ui = new UIBuilder();
95
- > var ele = document.getElementById('buttonContainer');
96
- > ele.innerHTML = ui.button('my button');
97
-
98
- ### Selenium Testing Integration
99
-
100
- ... Coming soon ...
101
-
102
- This is a little bit harder to explain, and is only for Ruby Selenium RC developers. The idea is that complex javascript applications usually reference most important DOM elements in javascript for things such as altering html or adding event handlers. What selenium integration in js2 means is that one can use annotations in his/her code to "mark" DOM elements instead of using xpaths.
103
-
104
- One of the pain points in Selenium testing is that the xpaths are always changing with each iteration of the view layer. In a complex javascript application, one has to maintain the references to DOM objects in javascript anyway, so this would be an easier way to maintain the Selenium references to the DOM.
105
-
106
- While this is available, its not quite ready for public consumption.
1
+ [JS2](http://github.com/jeffsu/js2) - Friendly Cross Browser Object Oriented Javascript
2
+ =======================================================================================
3
+
4
+ Classes and Methods
5
+ --------------------
6
+ To create a class, use the "class" keyword followed by matching curly braces. If the class
7
+ has an "initialize" method defined, it will run that right after an instance is created.
8
+ Getters and setters can be created by using the "property" keyword.
9
+
10
+
11
+ Here is an example of a class:
12
+
13
+ class Person {
14
+ // creates getName() and setName(name) methods
15
+ property name;
16
+
17
+ // creates getAge() and setAge(age) methods
18
+ property age;
19
+
20
+ // called after new Person(age) is called
21
+ function initialize(age) {
22
+ this.age = age;
23
+ }
24
+ }
25
+
26
+ var p = new Person(14);
27
+ p.setName("Jeff");
28
+ var age = p.getAge(); // 14
29
+
30
+ Modules/Mixins/Multiple Inheritance
31
+ -----------------------------------
32
+ JS2 uses a Ruby-inspired methodology for multiple inheritance. Here is an example
33
+ of how it works:
34
+
35
+ module Flyable {
36
+ function fly() {
37
+ alert("I believe I can fly!");
38
+ }
39
+ }
40
+
41
+ class Duck {
42
+ include Flyable;
43
+ }
44
+
45
+ var duck = new Duck();
46
+ duck.fly();
47
+
48
+ Syntactic Sugar
49
+ ---------------
50
+
51
+ *Foreach*: iterating through an array without having to manually create temp variables:
52
+
53
+ var items = [ 'foo', 'bar', 'baz' ]
54
+ foreach (var item in items) {
55
+ alert(item);
56
+ }
57
+
58
+ // with index
59
+ foreach (var item:i in items) {
60
+ alert(i + ':' + item);
61
+ }
62
+
63
+ *Currying*: tightly scoped anonymous functions to prevent memory leaks
64
+
65
+ var bigData = getBigData();
66
+ var inScope = getSmallData();
67
+
68
+ element.onClick = curry (evt) with (inScope, this) {
69
+ alert("curry" + inScope);
70
+ // variable "self" is available as the "this" in the outer scope
71
+ }
72
+
73
+
data/wiki/installation.md CHANGED
@@ -1,53 +1,13 @@
1
- ## Basic Installation and Usage
1
+ [JS2](http://github.com/jeffsu/js2) - Installation
2
+ =======================================================================================
2
3
 
3
- > gem install js2
4
- > js2 --help
5
- >
6
- > js2 --out-dir=/dir/to/write/js /dir/with/js2
4
+ 1. Install Ruby Gems
5
+ 2. Install js2
6
+ gem install js2
7
7
 
8
- ## For Rails
8
+ You should now have the js2 executable in your path. Running this command should bring up the
9
+ help page.
9
10
 
10
- This really depends on where you're writing your js2 files. Its recommended that you put it in app/js2, but its really up to you.
11
+ js2
11
12
 
12
- From the rails root directory
13
13
 
14
- > js2 --out-dir=./public/javascripts ./app/js2
15
-
16
- To daemonize it and have it routinely check for changes (every 0.5 secs):
17
-
18
- > js2 -d --out-dir=./public/javascripts ./app/js2
19
-
20
- ## Quick Tutorial
21
-
22
- In a new directory, do this:
23
-
24
- > mkdir js2
25
- > mkdir js
26
-
27
- Now create some js2 classes: vi js2/base.js2
28
-
29
- > class My.Base {
30
- > function sayHi () {
31
- > alert("hi");
32
- > }
33
- > }
34
-
35
- vi js2/concrete.js2
36
-
37
- > class My.Concrete {
38
- > function sayHello () {
39
- > alert("hello");
40
- > }
41
- > }
42
-
43
- compile:
44
-
45
- > js2 --out-dir=./js ./js2
46
-
47
- Be sure to include js/classes.js, js/base.js, and concrete.js (order matters as far as classes is concerned) in your browser.
48
-
49
- Now you can run this in javascript:
50
-
51
- > var obj = new My.Concrete();
52
- > obj.sayHi();
53
- > obj.sayHello();
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 7
9
- version: 0.1.7
8
+ - 8
9
+ version: 0.1.8
10
10
  platform: ruby
11
11
  authors:
12
12
  - Jeff Su
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-10-08 00:00:00 -07:00
17
+ date: 2010-10-21 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -30,7 +30,7 @@ dependencies:
30
30
  version: "0"
31
31
  type: :runtime
32
32
  version_requirements: *id001
33
- description: ""
33
+ description: Cross-Browser Object Oriented Javascript Compiler
34
34
  email: me@jeffsu.com
35
35
  executables:
36
36
  - js2
@@ -144,7 +144,7 @@ rubyforge_project: js2
144
144
  rubygems_version: 1.3.7
145
145
  signing_key:
146
146
  specification_version: 3
147
- summary: ""
147
+ summary: Cross-Browser Object Oriented Javascript Compiler
148
148
  test_files:
149
149
  - test/test_js2.rb
150
150
  - test/test_helper.rb