jim 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +28 -0
- data/README.rdoc +1 -1
- data/Rakefile +2 -1
- data/jim.gemspec +67 -9
- data/lib/jim/bundler.rb +14 -11
- data/lib/jim/cli.rb +51 -9
- data/lib/jim/index.rb +3 -7
- data/lib/jim/installer.rb +140 -22
- data/lib/jim/templates/commands +21 -6
- data/lib/jim/version_parser.rb +2 -3
- data/lib/jim.rb +19 -2
- data/test/fixtures/jimfile +3 -3
- data/test/fixtures/sammy-0.5.0/HISTORY.md +135 -0
- data/test/fixtures/sammy-0.5.0/LICENSE +22 -0
- data/test/fixtures/sammy-0.5.0/README.md +81 -0
- data/test/fixtures/sammy-0.5.0/Rakefile +174 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/README.md +23 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/Rakefile +15 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/app.rb +17 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/app.ru +3 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/app.js +106 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.cloudkit.js +840 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.js +19 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/sammy.js +1013 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/index.html.erb +11 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task.html.erb +4 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task_details.html.erb +4 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/views/app.sass +63 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/views/index.haml +18 -0
- data/test/fixtures/sammy-0.5.0/examples/form_handling/files/form.html +12 -0
- data/test/fixtures/sammy-0.5.0/examples/form_handling/index.html +65 -0
- data/test/fixtures/sammy-0.5.0/examples/hello_world/index.html +50 -0
- data/test/fixtures/sammy-0.5.0/examples/location_override/README.md +15 -0
- data/test/fixtures/sammy-0.5.0/examples/location_override/data.html +110 -0
- data/test/fixtures/sammy-0.5.0/examples/location_override/index.html +79 -0
- data/test/fixtures/sammy-0.5.0/examples/location_override/test.html +121 -0
- data/test/fixtures/sammy-0.5.0/lib/min/sammy-0.5.0.min.js +5 -0
- data/test/fixtures/sammy-0.5.0/lib/min/sammy-lastest.min.js +5 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.cache.js +117 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.haml.js +539 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.json.js +362 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.mustache.js +415 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.nested_params.js +118 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.storage.js +515 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.template.js +117 -0
- data/test/fixtures/sammy-0.5.0/lib/sammy.js +1367 -0
- data/test/fixtures/sammy-0.5.0/test/fixtures/partial +1 -0
- data/test/fixtures/sammy-0.5.0/test/fixtures/partial.html +1 -0
- data/test/fixtures/sammy-0.5.0/test/fixtures/partial.noengine +1 -0
- data/test/fixtures/sammy-0.5.0/test/fixtures/partial.template +1 -0
- data/test/fixtures/sammy-0.5.0/test/index.html +84 -0
- data/test/fixtures/sammy-0.5.0/test/test_sammy_application.js +953 -0
- data/test/fixtures/sammy-0.5.0/test/test_sammy_event_context.js +252 -0
- data/test/fixtures/sammy-0.5.0/test/test_sammy_location_proxy.js +91 -0
- data/test/fixtures/sammy-0.5.0/test/test_sammy_plugins.js +296 -0
- data/test/fixtures/sammy-0.5.0/test/test_sammy_storage.js +175 -0
- data/test/fixtures/sammy-0.5.0/test/test_server +27 -0
- data/test/fixtures/sammy-0.5.0/vendor/jquery-1.4.1.js +6078 -0
- data/test/fixtures/sammy-0.5.0/vendor/jquery-1.4.1.min.js +152 -0
- data/test/fixtures/sammy-0.5.0/vendor/jsdoc/doc.haml +58 -0
- data/test/fixtures/sammy-0.5.0/vendor/jsdoc/jsdoc.rb +143 -0
- data/test/fixtures/sammy-0.5.0/vendor/jslitmus.js +670 -0
- data/test/fixtures/sammy-0.5.0/vendor/qunit/qunit.css +119 -0
- data/test/fixtures/sammy-0.5.0/vendor/qunit/qunit.js +1043 -0
- data/test/fixtures/sammy-0.5.0/vendor/qunit-spec.js +127 -0
- data/test/helper.rb +23 -3
- data/test/test_jim_bundler.rb +9 -8
- data/test/test_jim_cli.rb +21 -12
- data/test/test_jim_installer.rb +152 -35
- data/test/test_jim_version_parser.rb +4 -0
- metadata +117 -27
- data/.document +0 -5
@@ -0,0 +1,4 @@
|
|
1
|
+
<li class="task <%= (task.attr('completed') ? 'completed' : '') %>" id="<%= task.attr('id') %>">
|
2
|
+
<input type="checkbox" <%= (task.attr('completed') ? 'checked="checked"' : '') %>" />
|
3
|
+
<a href="#/tasks/<%= task.attr('id') %>" class="entry"><%= task.attr('entry') %></a>
|
4
|
+
</li>
|
@@ -0,0 +1,63 @@
|
|
1
|
+
!font = "'Lucida Grande', Helvetica, Arial, sans-serif"
|
2
|
+
|
3
|
+
body
|
4
|
+
:font-family = !font
|
5
|
+
:color #333
|
6
|
+
:margin 0px
|
7
|
+
:background #F3F3F3
|
8
|
+
|
9
|
+
|
10
|
+
a:link, a:visited
|
11
|
+
:text-decoration none
|
12
|
+
:color #5588CA
|
13
|
+
a:hover
|
14
|
+
:color #333
|
15
|
+
:background #E8E8E8
|
16
|
+
:-moz-border-radius 2px
|
17
|
+
|
18
|
+
h1
|
19
|
+
:color #000
|
20
|
+
:margin 0px
|
21
|
+
:font-weight normal
|
22
|
+
|
23
|
+
a:link, a:visited
|
24
|
+
:color #000
|
25
|
+
a:hover
|
26
|
+
:color #5588CA
|
27
|
+
:background none
|
28
|
+
|
29
|
+
#header
|
30
|
+
:padding 5px 20px
|
31
|
+
:background #D7D7D7
|
32
|
+
:border-bottom 4px solid #C0C0C0
|
33
|
+
#main
|
34
|
+
:padding 15px
|
35
|
+
#tasks
|
36
|
+
:list-style-type none
|
37
|
+
:margin 5px 0px
|
38
|
+
:padding 0px
|
39
|
+
|
40
|
+
li
|
41
|
+
:margin 5px 0px
|
42
|
+
:padding 4px
|
43
|
+
a
|
44
|
+
:padding 2px
|
45
|
+
:font-size 18px
|
46
|
+
&.completed a
|
47
|
+
:text-decoration line-through
|
48
|
+
:color #999
|
49
|
+
|
50
|
+
#task_entry
|
51
|
+
input[type=text]
|
52
|
+
:width 100%
|
53
|
+
:font-size 18px
|
54
|
+
:padding 4px
|
55
|
+
:-moz-border-radius 4px
|
56
|
+
:border 1px solid #CCC
|
57
|
+
input[type=submit]
|
58
|
+
:-moz-border-radius 4px
|
59
|
+
:font-size 16px
|
60
|
+
:padding 4px 20px
|
61
|
+
:color #333
|
62
|
+
:background #ECECEC
|
63
|
+
:border 1px solid #CCC
|
@@ -0,0 +1,18 @@
|
|
1
|
+
%html{:xmlns=> "http://www.w3.org/1999/xhtml", 'xml:lang' => "en", :lang => "en"}
|
2
|
+
%head
|
3
|
+
%meta{'http-equiv' => "Content-Type", 'content' => "text/html; charset=utf-8"}
|
4
|
+
%title Backended
|
5
|
+
|
6
|
+
%link{:rel => 'stylesheet', :href => '/stylesheets/app.css', :media => 'screen'}
|
7
|
+
|
8
|
+
- ['jquery', 'jquery.cloudkit', 'sammy', 'app'].each do |js|
|
9
|
+
%script{:src => "/javascripts/#{js}.js", :type => 'text/javascript', :charset => 'utf-8'}
|
10
|
+
%body
|
11
|
+
#container
|
12
|
+
#header
|
13
|
+
%h1
|
14
|
+
%a{:href => '#/', :title => 'Home'} Sammy Todo
|
15
|
+
#error{:style => 'display:none'}
|
16
|
+
%span.close x
|
17
|
+
#main
|
18
|
+
#debug
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<form action="#/pretend/post/url" method="post">
|
2
|
+
<p><label for="name">Name:</label><input type="text" name="name" /></p>
|
3
|
+
<p><label for="email">Email:</label><input type="text" name="email" /></p>
|
4
|
+
<p><label for="role_admin">Admin?</label><input type="checkbox" name="roles[]" value="admin" id="role_admin"/></p>
|
5
|
+
<p><label for="role_author">Author?</label><input type="checkbox" name="roles[]" value="author" id="role_author"/></p>
|
6
|
+
<p><input type="submit" value="Post!" /></p>
|
7
|
+
</form>
|
8
|
+
|
9
|
+
<h3>Plain old form</h3>
|
10
|
+
<form method="post" action="/i_should_submit">
|
11
|
+
<p><input type="submit" value="Dont press me!" /></p>
|
12
|
+
</form>
|
@@ -0,0 +1,65 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
|
4
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
5
|
+
<head>
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
7
|
+
|
8
|
+
<title>Form Handling</title>
|
9
|
+
|
10
|
+
<style type="text/css" media="screen">
|
11
|
+
|
12
|
+
</style>
|
13
|
+
|
14
|
+
<script src="../../vendor/jquery-1.4.1.min.js" type="text/javascript" charset="utf-8"></script>
|
15
|
+
<script src="../../lib/sammy.js" type="text/javascript" charset="utf-8"></script>
|
16
|
+
<script type="text/javascript" charset="utf-8">
|
17
|
+
// ;(function($) {
|
18
|
+
var app = new Sammy.Application(function() { with(this) {
|
19
|
+
debug = true;
|
20
|
+
element_selector = '#main';
|
21
|
+
form_fields = null;
|
22
|
+
|
23
|
+
get('#/', function() { with(this) {
|
24
|
+
$element().text('Click form!');
|
25
|
+
}});
|
26
|
+
|
27
|
+
get('#/form', function() { with(this) {
|
28
|
+
partial('files/form.html');
|
29
|
+
}});
|
30
|
+
|
31
|
+
post('#/pretend/post/url', function() { with(this) {
|
32
|
+
form_fields = params;
|
33
|
+
redirect('#/display');
|
34
|
+
}});
|
35
|
+
|
36
|
+
get('#/display', function() { with(this) {
|
37
|
+
if (form_fields) {
|
38
|
+
$element().html(form_fields.toHTML());
|
39
|
+
} else {
|
40
|
+
redirect('#/form')
|
41
|
+
}
|
42
|
+
}});
|
43
|
+
|
44
|
+
}});
|
45
|
+
|
46
|
+
$(function() {
|
47
|
+
app.run('#/');
|
48
|
+
});
|
49
|
+
|
50
|
+
// })(jQuery);
|
51
|
+
</script>
|
52
|
+
|
53
|
+
</head>
|
54
|
+
|
55
|
+
<body>
|
56
|
+
<div id="container">
|
57
|
+
<div id="main">
|
58
|
+
</div>
|
59
|
+
<ul id="link">
|
60
|
+
<li><a href="#/form">Form!</a></li>
|
61
|
+
<li><a href="#/">Back</a></li>
|
62
|
+
</ul>
|
63
|
+
</div>
|
64
|
+
</body>
|
65
|
+
</html>
|
@@ -0,0 +1,50 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
|
4
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
5
|
+
<head>
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
7
|
+
|
8
|
+
<title>Hello World</title>
|
9
|
+
|
10
|
+
<style type="text/css" media="screen">
|
11
|
+
|
12
|
+
</style>
|
13
|
+
|
14
|
+
<script src="../../vendor/jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
|
15
|
+
<script src="../../lib/sammy.js" type="text/javascript" charset="utf-8"></script>
|
16
|
+
<script type="text/javascript" charset="utf-8">
|
17
|
+
;(function($) {
|
18
|
+
var app = new Sammy.Application(function() {
|
19
|
+
with(this) {
|
20
|
+
|
21
|
+
get('#/', function() { with(this) {
|
22
|
+
$('#main').text('');
|
23
|
+
}});
|
24
|
+
|
25
|
+
get('#/test', function() { with(this) {
|
26
|
+
$('#main').text('Hello World');
|
27
|
+
}});
|
28
|
+
|
29
|
+
}
|
30
|
+
});
|
31
|
+
|
32
|
+
$(function() {
|
33
|
+
app.run()
|
34
|
+
});
|
35
|
+
})(jQuery);
|
36
|
+
</script>
|
37
|
+
|
38
|
+
</head>
|
39
|
+
|
40
|
+
<body>
|
41
|
+
<div id="container">
|
42
|
+
<div id="main">
|
43
|
+
</div>
|
44
|
+
<ul id="link">
|
45
|
+
<li><a href="#/test">Click me!</a></li>
|
46
|
+
<li><a href="#/">Back</a></li>
|
47
|
+
</div>
|
48
|
+
</div>
|
49
|
+
</body>
|
50
|
+
</html>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Sammy
|
2
|
+
|
3
|
+
## Location Override Example
|
4
|
+
|
5
|
+
These two examples represent ways of overriding the default location ability to get and set the location from somewhere other then
|
6
|
+
|
7
|
+
window.location.hash
|
8
|
+
|
9
|
+
### index.html
|
10
|
+
|
11
|
+
Uses a text input as a 'location bar'.
|
12
|
+
|
13
|
+
### data.html
|
14
|
+
|
15
|
+
Uses jQuery's $.data() accessor to get/set the location from within the applications element. (Submitted by CodeOfficer)
|
@@ -0,0 +1,110 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
|
4
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
5
|
+
<head>
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
7
|
+
<title>Location Demo</title>
|
8
|
+
<style type="text/css" media="screen">
|
9
|
+
#main { background-color: #CCCCCC; }
|
10
|
+
</style>
|
11
|
+
|
12
|
+
<script src="../../vendor/jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
|
13
|
+
<script src="../../lib/sammy.js" type="text/javascript" charset="utf-8"></script>
|
14
|
+
|
15
|
+
<script type="text/javascript" charset="utf-8">
|
16
|
+
;(function($) {
|
17
|
+
var app = new Sammy.Application(function() { with(this) {
|
18
|
+
debug = true;
|
19
|
+
element_selector = '#main';
|
20
|
+
|
21
|
+
// overide getLocation
|
22
|
+
this.getLocation = function() {
|
23
|
+
if (this.$element().data('location') == undefined) {
|
24
|
+
this.$element().data('location', '');
|
25
|
+
};
|
26
|
+
return this.$element().data('location');
|
27
|
+
};
|
28
|
+
|
29
|
+
// overide setLocation
|
30
|
+
this.setLocation = function(new_location) {
|
31
|
+
return this.$element().data('location', new_location);
|
32
|
+
};
|
33
|
+
|
34
|
+
get('#/', function() { with(this) {
|
35
|
+
$("#output").text("matched: #/");
|
36
|
+
}});
|
37
|
+
|
38
|
+
get('#/link/:id', function() { with(this) {
|
39
|
+
$("#output").text("matched: #/link/:" + params['id']);
|
40
|
+
}});
|
41
|
+
|
42
|
+
post('#/form', function() { with(this) {
|
43
|
+
$("#output").text("post matched: #/form - params[field] = " + params['field']);
|
44
|
+
return false;
|
45
|
+
}});
|
46
|
+
|
47
|
+
put('#/form', function() { with(this) {
|
48
|
+
$("#output").text("put matched: #/form - params[field] = " + params['field']);
|
49
|
+
return false;
|
50
|
+
}});
|
51
|
+
|
52
|
+
bind('run', function() { with(this) {
|
53
|
+
var context = this;
|
54
|
+
var element = context.$element();
|
55
|
+
|
56
|
+
// intercept click events manually
|
57
|
+
// we dont want the url to change for matched routes
|
58
|
+
$('a', element).bind('click', function(e) {
|
59
|
+
var path = $(this).attr('href');
|
60
|
+
if (path.match(/^#/)) {
|
61
|
+
context.redirect(path);
|
62
|
+
return false;
|
63
|
+
} else {
|
64
|
+
return true;
|
65
|
+
}
|
66
|
+
});
|
67
|
+
|
68
|
+
}});
|
69
|
+
|
70
|
+
}});
|
71
|
+
|
72
|
+
$(function() {
|
73
|
+
app.run('#/');
|
74
|
+
});
|
75
|
+
|
76
|
+
})(jQuery);
|
77
|
+
</script>
|
78
|
+
|
79
|
+
</head>
|
80
|
+
|
81
|
+
<body>
|
82
|
+
<div id="container">
|
83
|
+
|
84
|
+
<div id="main">
|
85
|
+
<ul>
|
86
|
+
<li><a href="data.html">reset</a></li>
|
87
|
+
<li><a href="#/">#/</a></li>
|
88
|
+
<li><a href="#/link/id">#/link/id</a></li>
|
89
|
+
</ul>
|
90
|
+
|
91
|
+
<form action="#/form" method="put">
|
92
|
+
<p><input type="text" name="field" value="WAS PUT" id="field"/></p>
|
93
|
+
<p><input type="submit" value="Continue →"/></p>
|
94
|
+
</form>
|
95
|
+
|
96
|
+
<form action="#/form" method="post">
|
97
|
+
<p><input type="text" name="field" value="WAS POSTED" id="field"/></p>
|
98
|
+
<p><input type="submit" value="Continue →"/></p>
|
99
|
+
</form>
|
100
|
+
</div>
|
101
|
+
|
102
|
+
<h1>Results</h1>
|
103
|
+
|
104
|
+
<div id="output">
|
105
|
+
</div>
|
106
|
+
|
107
|
+
</div>
|
108
|
+
|
109
|
+
</body>
|
110
|
+
</html>
|
@@ -0,0 +1,79 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
|
4
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
5
|
+
<head>
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
7
|
+
|
8
|
+
<title>Form Handling</title>
|
9
|
+
|
10
|
+
<style type="text/css" media="screen">
|
11
|
+
|
12
|
+
</style>
|
13
|
+
|
14
|
+
<script src="../../vendor/jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
|
15
|
+
<script src="../../lib/sammy.js" type="text/javascript" charset="utf-8"></script>
|
16
|
+
<script type="text/javascript" charset="utf-8">
|
17
|
+
;(function($) {
|
18
|
+
var app = new Sammy.Application(function() { with(this) {
|
19
|
+
debug = true;
|
20
|
+
element_selector = '#main';
|
21
|
+
// form_fields = null;
|
22
|
+
|
23
|
+
this.getLocation = function() {
|
24
|
+
return $('#location').val().toString();
|
25
|
+
};
|
26
|
+
|
27
|
+
this.setLocation = function(new_location) {
|
28
|
+
return $('#location').val(new_location);
|
29
|
+
}
|
30
|
+
|
31
|
+
get('/', function() { with(this) {
|
32
|
+
$element().html('Enter a URL in the field above! Try /user/...');
|
33
|
+
}});
|
34
|
+
|
35
|
+
get('/user/:name', function() { with(this) {
|
36
|
+
$element().html('Youre at ' + params['name'] + "'s page. <a href='/' class='back'>Go Back</a>.");
|
37
|
+
}});
|
38
|
+
|
39
|
+
bind('back', function() { with(this) {
|
40
|
+
log('back!');
|
41
|
+
redirect('/');
|
42
|
+
}});
|
43
|
+
|
44
|
+
bind('run', function() {
|
45
|
+
var context = this;
|
46
|
+
$('a').live('click', function() {
|
47
|
+
var href = $(this).attr('href');
|
48
|
+
if (href.match(/^\//)) { // local link
|
49
|
+
context.redirect(href);
|
50
|
+
return false;
|
51
|
+
} else {
|
52
|
+
return true; // execute actual href
|
53
|
+
}
|
54
|
+
});
|
55
|
+
});
|
56
|
+
|
57
|
+
}});
|
58
|
+
|
59
|
+
$(function() {
|
60
|
+
app.run('/');
|
61
|
+
});
|
62
|
+
|
63
|
+
})(jQuery);
|
64
|
+
</script>
|
65
|
+
|
66
|
+
</head>
|
67
|
+
|
68
|
+
<body>
|
69
|
+
<div id="container">
|
70
|
+
<input id="location" type="text" />
|
71
|
+
<div id="main">
|
72
|
+
|
73
|
+
</div>
|
74
|
+
<ul>
|
75
|
+
<li><a href="/">Go Home</a></li>
|
76
|
+
<li><a href="/user/blah">Check out this user</a></li>
|
77
|
+
</div>
|
78
|
+
</body>
|
79
|
+
</html>
|
@@ -0,0 +1,121 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
|
4
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
5
|
+
<head>
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
7
|
+
<title>Location Demo</title>
|
8
|
+
<style type="text/css" media="screen">
|
9
|
+
#main { background-color: #CCCCCC; }
|
10
|
+
#output { background-color: #FF6666; }
|
11
|
+
</style>
|
12
|
+
|
13
|
+
<script src="../../vendor/jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
|
14
|
+
<script src="../../lib/sammy.js" type="text/javascript" charset="utf-8"></script>
|
15
|
+
|
16
|
+
<script type="text/javascript" charset="utf-8">
|
17
|
+
;(function($) {
|
18
|
+
|
19
|
+
// ----------------------------------------------------------------
|
20
|
+
|
21
|
+
Sammy.Application.prototype.getLocation = function() {
|
22
|
+
if (this.$element().data('appState') == undefined) {
|
23
|
+
this.$element().data('appState', '');
|
24
|
+
};
|
25
|
+
return this.$element().data('appState');
|
26
|
+
};
|
27
|
+
|
28
|
+
Sammy.Application.prototype.setLocation = function(newState) {
|
29
|
+
console.log('setLocation called with:', newState);
|
30
|
+
return this.$element().data('appState', newState);
|
31
|
+
};
|
32
|
+
|
33
|
+
// ----------------------------------------------------------------
|
34
|
+
|
35
|
+
var app = new Sammy.Application(function() { with(this) {
|
36
|
+
element_selector = '#main';
|
37
|
+
|
38
|
+
get('#/link', function() { with(this) {
|
39
|
+
$("#output").text("matched: #/link");
|
40
|
+
redirect('#/test_route');
|
41
|
+
}});
|
42
|
+
|
43
|
+
post('#/form', function() { with(this) {
|
44
|
+
$("#output").text("post matched: #/form (REDIRECT UNSUCCESSFUL)");
|
45
|
+
redirect('#/test_route');
|
46
|
+
}});
|
47
|
+
|
48
|
+
get('#/test_route', function() { with(this) {
|
49
|
+
$("#output").text("matched: #/test_route (REDIRECT SUCCESSFUL)");
|
50
|
+
}});
|
51
|
+
|
52
|
+
bind('run', function() { with(this) {
|
53
|
+
var context = this;
|
54
|
+
var element = context.$element();
|
55
|
+
|
56
|
+
// intercept click events manually
|
57
|
+
// we dont want the url to change for matched routes
|
58
|
+
$('a', element).bind('click', function(e) {
|
59
|
+
var path = $(this).attr('href');
|
60
|
+
if (path.match(/^#/)) {
|
61
|
+
context.redirect(path);
|
62
|
+
return false;
|
63
|
+
} else {
|
64
|
+
return true;
|
65
|
+
}
|
66
|
+
});
|
67
|
+
|
68
|
+
}});
|
69
|
+
}});
|
70
|
+
|
71
|
+
// ----------------------------------------------------------------
|
72
|
+
|
73
|
+
$(function() {
|
74
|
+
app.run();
|
75
|
+
});
|
76
|
+
|
77
|
+
})(jQuery);
|
78
|
+
</script>
|
79
|
+
|
80
|
+
</head>
|
81
|
+
|
82
|
+
<body>
|
83
|
+
<div id="container">
|
84
|
+
|
85
|
+
<h2>Using <strong>redirects</strong> with the new location storage.</h2>
|
86
|
+
|
87
|
+
<p>This example defines 2 routes, <strong>#/link</strong> and <strong>#/form</strong> ... both of which execute a redirect to <strong>#/test_route</strong></p>
|
88
|
+
|
89
|
+
<p><u>When #/link route triggers the redirect</u>, the behavior is as expected every time. And when I look in console I can see setLocation being called <strong>twice</strong> as I'd expect.</p>
|
90
|
+
|
91
|
+
<p><u>When #/form route triggers the redirect</u>, the behavior seems inconsistent.</p>
|
92
|
+
|
93
|
+
<p>The first form submit is successful, the redirect occurs and the body of the #/test_route executes. BUT! looking in console, we see setLocation only being called <strong>once</strong> for the #/test_route/ and not at all for the #/form route preceeding it.</p>
|
94
|
+
|
95
|
+
<p>Because #/test_route was the last location set, and because the #/form route never did a setLocation anyway, repeated clicks to submit the form will not be heard.</p>
|
96
|
+
|
97
|
+
<p>I kind of expect that when a form submission is caught it will trigger a Setlocation ... but looking in _checkFormSubmission, i see that the form routes are manually run here via runRoute, bypassing setLocation entirely!</p>
|
98
|
+
|
99
|
+
<p>Any thoughts on this? I know that recording app state via data attributes isn't a core feature of sammy, but I'm curious to hear if you think caught form submits should still bypass setLocation etc.</p>
|
100
|
+
|
101
|
+
<div id="main">
|
102
|
+
<ul>
|
103
|
+
<li><a href="quirkey.html">reset</a></li>
|
104
|
+
<li><a href="#/link">#/link</a></li>
|
105
|
+
</ul>
|
106
|
+
|
107
|
+
<form action="#/form" method="post">
|
108
|
+
<p><input type="text" name="field" value="WAS POSTED" id="field"/></p>
|
109
|
+
<p><input type="submit" value="Continue →"/></p>
|
110
|
+
</form>
|
111
|
+
</div>
|
112
|
+
|
113
|
+
<h1>Results</h1>
|
114
|
+
|
115
|
+
<div id="output">
|
116
|
+
</div>
|
117
|
+
|
118
|
+
</div>
|
119
|
+
|
120
|
+
</body>
|
121
|
+
</html>
|
@@ -0,0 +1,5 @@
|
|
1
|
+
// -- Sammy -- /sammy.js
|
2
|
+
// http://code.quirkey.com/sammy
|
3
|
+
// Version: 0.5.0
|
4
|
+
// Built: Mon Feb 15 14:13:25 -0500 2010
|
5
|
+
(function(g){var d="([^/]+)",f=/:([\w\d]+)/g,c=/\?([^#]*)$/,a=decodeURIComponent,b=function(h){return function(i,j){return this.route.apply(this,[h,i,j])}},e=[];Sammy=function(){var i=g.makeArray(arguments),j,h;Sammy.apps=Sammy.apps||{};if(i.length==0||i[0]&&g.isFunction(i[0])){return Sammy.apply(Sammy,["body"].concat(i))}else{if(typeof(h=i.shift())=="string"){j=Sammy.apps[h]||new Sammy.Application();j.element_selector=h;if(i.length>0){g.each(i,function(k,l){j.use(l)})}if(j.element_selector!=h){delete Sammy.apps[h]}Sammy.apps[j.element_selector]=j;return j}}};Sammy.VERSION="0.5.0";Sammy.addLogger=function(h){e.push(h)};Sammy.log=function(){var h=g.makeArray(arguments);h.unshift("["+Date()+"]");g.each(e,function(k,j){j.apply(Sammy,h)})};if(typeof window.console!="undefined"){if(g.isFunction(console.log.apply)){Sammy.addLogger(function(){window.console.log.apply(console,arguments)})}else{Sammy.addLogger(function(){window.console.log(arguments)})}}else{if(typeof console!="undefined"){Sammy.addLogger(function(){console.log.apply(console,arguments)})}}Sammy.Object=function(h){return g.extend(this,h||{})};g.extend(Sammy.Object.prototype,{toHash:function(){var h={};g.each(this,function(j,i){if(!g.isFunction(i)){h[j]=i}});return h},toHTML:function(){var h="";g.each(this,function(j,i){if(!g.isFunction(i)){h+="<strong>"+j+"</strong> "+i+"<br />"}});return h},uuid:function(){if(typeof this._uuid=="undefined"||!this._uuid){this._uuid=(new Date()).getTime()+"-"+parseInt(Math.random()*1000)}return this._uuid},keys:function(h){var i=[];for(var j in this){if(!g.isFunction(this[j])||!h){i.push(j)}}return i},has:function(h){return this[h]&&g.trim(this[h].toString())!=""},join:function(){var i=g.makeArray(arguments);var h=i.shift();return i.join(h)},log:function(){Sammy.log.apply(Sammy,arguments)},toString:function(h){var i=[];g.each(this,function(l,j){if(!g.isFunction(j)||h){i.push('"'+l+'": '+j.toString())}});return"Sammy.Object: {"+i.join(",")+"}"}});Sammy.HashLocationProxy=function(i,h){this.app=i;if("onhashchange" in window){Sammy.log("native hash change exists, using");this.is_native=true}else{Sammy.log("no native hash change, falling back to polling");this.is_native=false;this._startPolling(h)}};Sammy.HashLocationProxy.prototype={bind:function(){var h=this.app;g(window).bind("hashchange."+this.app.eventNamespace(),function(){h.trigger("location-changed")})},unbind:function(){g(window).die("hashchange."+this.app.eventNamespace())},getLocation:function(){var h=window.location.toString().match(/^[^#]*(#.+)$/);return h?h[1]:""},setLocation:function(h){return window.location=h},_startPolling:function(j){var i=this;if(!Sammy.HashLocationProxy._interval){if(!j){j=10}var h=function(){current_location=i.getLocation();if(!Sammy.HashLocationProxy._last_location||current_location!=Sammy.HashLocationProxy._last_location){setTimeout(function(){g(window).trigger("hashchange")},1)}Sammy.HashLocationProxy._last_location=current_location};h();Sammy.HashLocationProxy._interval=setInterval(h,j);g(window).bind("unload",function(){clearInterval(Sammy.HashLocationProxy._interval)})}}};Sammy.DataLocationProxy=function(i,h){this.app=i;this.data_name=h||"sammy-location"};Sammy.DataLocationProxy.prototype={bind:function(){var h=this;this.app.$element().bind("setData",function(j,i){if(i==h.data_name){h.app.trigger("location-changed")}})},unbind:function(){this.app.$element().die("setData")},getLocation:function(){return this.app.$element().data(this.data_name)},setLocation:function(h){return this.app.$element().data(this.data_name,h)}};Sammy.Application=function(h){var i=this;this.routes={};this.listeners=new Sammy.Object({});this.arounds=[];this.befores=[];this.namespace=this.uuid();this.context_prototype=function(){Sammy.EventContext.apply(this,arguments)};this.context_prototype.prototype=new Sammy.EventContext();if(g.isFunction(h)){h.apply(this,[this])}if(!this.location_proxy){this.location_proxy=new Sammy.HashLocationProxy(i,this.run_interval_every)}if(this.debug){this.bindToAllEvents(function(k,j){i.log(i.toString(),k.cleaned_type,j||{})})}};Sammy.Application.prototype=g.extend({},Sammy.Object.prototype,{ROUTE_VERBS:["get","post","put","delete"],APP_EVENTS:["run","unload","lookup-route","run-route","route-found","event-context-before","event-context-after","changed","error-404","check-form-submission","redirect"],_last_route:null,_running:false,data_store_name:"sammy-app",element_selector:"body",debug:false,silence_404:true,run_interval_every:50,location_proxy:null,template_engine:null,toString:function(){return"Sammy.Application:"+this.element_selector},$element:function(){return g(this.element_selector)},use:function(){var h=g.makeArray(arguments);var i=h.shift();try{h.unshift(this);i.apply(this,h)}catch(j){if(typeof i=="undefined"){throw ("Error: called use() but plugin is not defined")}else{if(!g.isFunction(i)){throw ("Error: called use() but '"+i.toString()+"' is not a function")}else{throw (j)}}}return this},route:function(k,i,m){var j=this,l=[],h;if(!m&&g.isFunction(i)){i=k;m=i;k="any"}k=k.toLowerCase();if(i.constructor==String){f.lastIndex=0;while((path_match=f.exec(i))!=null){l.push(path_match[1])}i=new RegExp("^"+i.replace(f,d)+"$")}if(typeof m=="string"){m=j[m]}h=function(n){var o={verb:n,path:i,callback:m,param_names:l};j.routes[n]=j.routes[n]||[];j.routes[n].push(o)};if(k==="any"){g.each(this.ROUTE_VERBS,function(o,n){h(n)})}else{h(k)}return this},get:b("get"),post:b("post"),put:b("put"),del:b("delete"),any:b("any"),mapRoutes:function(i){var h=this;g.each(i,function(j,k){h.route.apply(h,k)});return this},eventNamespace:function(){return[this.data_store_name,this.namespace].join("-")},bind:function(h,j,l){var k=this;if(typeof l=="undefined"){l=j}var i=function(){var o,m,n;o=arguments[0];n=arguments[1];if(n&&n.context){m=n.context;delete n.context}else{m=new k.context_prototype(k,"bind",o.type,n)}o.cleaned_type=o.type.replace(k.eventNamespace(),"");l.apply(m,[o,n])};if(!this.listeners[h]){this.listeners[h]=[]}this.listeners[h].push(i);if(this.isRunning()){this._listen(h,i)}return this},trigger:function(h,i){this.$element().trigger([h,this.eventNamespace()].join("."),[i]);return this},refresh:function(){this.last_location=null;this.trigger("location-changed");return this},before:function(h,i){if(g.isFunction(h)){i=h;h={}}this.befores.push([h,i]);return this},after:function(h){return this.bind("event-context-after",h)},around:function(h){this.arounds.push(h);return this},isRunning:function(){return this._running},helpers:function(h){g.extend(this.context_prototype.prototype,h);return this},helper:function(h,i){this.context_prototype.prototype[h]=i;return this},run:function(h){if(this.isRunning()){return false}var i=this;g.each(this.listeners.toHash(),function(j,k){g.each(k,function(m,l){i._listen(j,l)})});this.trigger("run",{start_url:h});this._running=true;this.$element().data(this.data_store_name,this);this.last_location=null;if(this.getLocation()==""&&typeof h!="undefined"){this.setLocation(h)}this._checkLocation();this.location_proxy.bind();this.bind("location-changed",function(){i._checkLocation()});this.bind("submit",function(k){var j=i._checkFormSubmission(g(k.target).closest("form"));return(j===false)?k.preventDefault():false});g("body").bind("onunload",function(){i.unload()});return this.trigger("changed")},unload:function(){if(!this.isRunning()){return false}var h=this;this.trigger("unload");this.location_proxy.unbind();this.$element().unbind("submit").removeClass(h.eventNamespace());this.$element().removeData(this.data_store_name);g.each(this.listeners.toHash(),function(i,j){g.each(j,function(l,k){h._unlisten(i,k)})});this._running=false;return this},bindToAllEvents:function(i){var h=this;g.each(this.APP_EVENTS,function(j,k){h.bind(k,i)});g.each(this.listeners.keys(true),function(k,j){if(h.APP_EVENTS.indexOf(j)==-1){h.bind(j,i)}});return this},routablePath:function(h){return h.replace(c,"")},lookupRoute:function(k,i){var j=this,h=false;this.trigger("lookup-route",{verb:k,path:i});if(typeof this.routes[k]!="undefined"){g.each(this.routes[k],function(m,l){if(j.routablePath(i).match(l.path)){h=l;return false}})}return h},runRoute:function(i,r,k){this.log("runRoute",[i,r].join(" "));this.trigger("run-route",{verb:i,path:r,params:k});if(typeof k=="undefined"){k={}}g.extend(k,this._parseQueryString(r));var j=this,h,n,l,m,q,o,p=this.lookupRoute(i,r);if(p){this.trigger("route-found",{route:p});if((path_params=p.path.exec(this.routablePath(r)))!=null){path_params.shift();g.each(path_params,function(s,t){if(p.param_names[s]){k[p.param_names[s]]=a(t)}else{if(!k.splat){k.splat=[]}k.splat.push(a(t))}})}h=new this.context_prototype(this,i,r,k);l=this.arounds.slice(0);q=this.befores.slice(0);n=function(){var s;while(q.length>0){o=q.shift();if(j.contextMatchesOptions(h,o[0])){s=o[1].apply(h,[h]);if(s===false){return false}}}j.last_route=p;h.trigger("event-context-before",{context:h});s=p.callback.apply(h,[h]);h.trigger("event-context-after",{context:h});return s};g.each(l.reverse(),function(s,t){var u=n;n=function(){return t.apply(h,[u])}});return n()}else{this.notFound(i,r)}},contextMatchesOptions:function(k,m,i){var j=m;if(typeof j==="undefined"||j=={}){return true}if(typeof i==="undefined"){i=true}if(typeof j==="string"||g.isFunction(j.test)){j={path:j}}if(j.only){return this.contextMatchesOptions(k,j.only,true)}else{if(j.except){return this.contextMatchesOptions(k,j.except,false)}}var h=true,l=true;if(j.path){if(g.isFunction(j.path.test)){h=j.path.test(k.path)}else{h=(j.path.toString()===k.path)}}if(j.verb){l=j.verb===k.verb}return i?(l&&h):!(l&&h)},getLocation:function(){return this.location_proxy.getLocation()},setLocation:function(h){return this.location_proxy.setLocation(h)},swap:function(h){return this.$element().html(h)},notFound:function(i,h){this.trigger("error-404",{verb:i,path:h});throw ("404 Not Found "+i+" "+h)},_checkLocation:function(){try{var h,i;h=this.getLocation();if(h!=this.last_location){i=this.runRoute("get",h)}this.last_location=h}catch(j){this.last_location=h;if(j.toString().match(/^404/)&&this.silence_404){return i}else{throw (j)}}return i},_checkFormSubmission:function(j){var h,l,n,m,i;this.trigger("check-form-submission",{form:j});h=g(j);l=h.attr("action");n=g.trim(h.attr("method").toString().toLowerCase());if(!n||n==""){n="get"}this.log("_checkFormSubmission",h,l,n);m=g.extend({},this._parseFormParams(h),{"$form":h});try{i=this.runRoute(n,l,m)}catch(k){if(k.toString().match(/^404/)&&this.silence_404){return true}else{throw (k)}}return(typeof i=="undefined")?false:i},_parseFormParams:function(h){var i={};g.each(h.serializeArray(),function(j,k){if(i[k.name]){if(g.isArray(i[k.name])){i[k.name].push(k.value)}else{i[k.name]=[i[k.name],k.value]}}else{i[k.name]=k.value}});return i},_parseQueryString:function(m){var k={},l,j,n,h;l=m.match(c);if(l){j=l[1].split("&");for(h=0;h<j.length;h+=1){n=j[h].split("=");k[n[0]]=a(n[1])}}return k},_listen:function(h,i){return this.$element().bind([h,this.eventNamespace()].join("."),i)},_unlisten:function(h,i){return this.$element().unbind([h,this.eventNamespace()].join("."),i)}});Sammy.EventContext=function(k,j,h,i){this.app=k;this.verb=j;this.path=h;this.params=new Sammy.Object(i)};Sammy.EventContext.prototype=g.extend({},Sammy.Object.prototype,{$element:function(){return this.app.$element()},partial:function(p,l,o){var h,k,n,m,j="partial:"+p,i=this;if((n=p.match(/\.([^\.]+)$/))){n=n[1]}if((!n||!g.isFunction(i[n]))&&this.app.template_engine){n=this.app.template_engine}if(n&&!g.isFunction(n)&&g.isFunction(i[n])){n=i[n]}if(!o&&g.isFunction(l)){o=l;l={}}m=(g.isArray(l)?l:[l||{}]),k=function(q){var r=q,s="";g.each(m,function(t,u){g.extend(u,i);if(g.isFunction(n)){r=n.apply(i,[q,u])}s+=r;if(o){return o.apply(i,[r,t])}});if(!o){i.app.swap(s)}i.trigger("changed")};if(this.app.cache_partials&&this.cache(j)){k.apply(i,[this.cache(j)])}else{g.get(p,function(q){if(i.app.cache_partials){i.cache(j,q)}k.apply(i,[q])})}},redirect:function(){var j,i=g.makeArray(arguments),h=this.app.getLocation();if(i.length>1){i.unshift("/");j=this.join.apply(this,i)}else{j=i[0]}this.trigger("redirect",{to:j});this.app.last_location=this.path;this.app.setLocation(j);if(h==j){this.app.trigger("location-changed")}},trigger:function(h,i){if(typeof i=="undefined"){i={}}if(!i.context){i.context=this}return this.app.trigger(h,i)},eventNamespace:function(){return this.app.eventNamespace()},notFound:function(){return this.app.notFound(this.verb,this.path)},toString:function(){return"Sammy.EventContext: "+[this.verb,this.path,this.params].join(" ")}});g.sammy=Sammy})(jQuery);
|
@@ -0,0 +1,5 @@
|
|
1
|
+
// -- Sammy -- /sammy.js
|
2
|
+
// http://code.quirkey.com/sammy
|
3
|
+
// Version: 0.5.0
|
4
|
+
// Built: Mon Feb 15 14:13:25 -0500 2010
|
5
|
+
(function(g){var d="([^/]+)",f=/:([\w\d]+)/g,c=/\?([^#]*)$/,a=decodeURIComponent,b=function(h){return function(i,j){return this.route.apply(this,[h,i,j])}},e=[];Sammy=function(){var i=g.makeArray(arguments),j,h;Sammy.apps=Sammy.apps||{};if(i.length==0||i[0]&&g.isFunction(i[0])){return Sammy.apply(Sammy,["body"].concat(i))}else{if(typeof(h=i.shift())=="string"){j=Sammy.apps[h]||new Sammy.Application();j.element_selector=h;if(i.length>0){g.each(i,function(k,l){j.use(l)})}if(j.element_selector!=h){delete Sammy.apps[h]}Sammy.apps[j.element_selector]=j;return j}}};Sammy.VERSION="0.5.0";Sammy.addLogger=function(h){e.push(h)};Sammy.log=function(){var h=g.makeArray(arguments);h.unshift("["+Date()+"]");g.each(e,function(k,j){j.apply(Sammy,h)})};if(typeof window.console!="undefined"){if(g.isFunction(console.log.apply)){Sammy.addLogger(function(){window.console.log.apply(console,arguments)})}else{Sammy.addLogger(function(){window.console.log(arguments)})}}else{if(typeof console!="undefined"){Sammy.addLogger(function(){console.log.apply(console,arguments)})}}Sammy.Object=function(h){return g.extend(this,h||{})};g.extend(Sammy.Object.prototype,{toHash:function(){var h={};g.each(this,function(j,i){if(!g.isFunction(i)){h[j]=i}});return h},toHTML:function(){var h="";g.each(this,function(j,i){if(!g.isFunction(i)){h+="<strong>"+j+"</strong> "+i+"<br />"}});return h},uuid:function(){if(typeof this._uuid=="undefined"||!this._uuid){this._uuid=(new Date()).getTime()+"-"+parseInt(Math.random()*1000)}return this._uuid},keys:function(h){var i=[];for(var j in this){if(!g.isFunction(this[j])||!h){i.push(j)}}return i},has:function(h){return this[h]&&g.trim(this[h].toString())!=""},join:function(){var i=g.makeArray(arguments);var h=i.shift();return i.join(h)},log:function(){Sammy.log.apply(Sammy,arguments)},toString:function(h){var i=[];g.each(this,function(l,j){if(!g.isFunction(j)||h){i.push('"'+l+'": '+j.toString())}});return"Sammy.Object: {"+i.join(",")+"}"}});Sammy.HashLocationProxy=function(i,h){this.app=i;if("onhashchange" in window){Sammy.log("native hash change exists, using");this.is_native=true}else{Sammy.log("no native hash change, falling back to polling");this.is_native=false;this._startPolling(h)}};Sammy.HashLocationProxy.prototype={bind:function(){var h=this.app;g(window).bind("hashchange."+this.app.eventNamespace(),function(){h.trigger("location-changed")})},unbind:function(){g(window).die("hashchange."+this.app.eventNamespace())},getLocation:function(){var h=window.location.toString().match(/^[^#]*(#.+)$/);return h?h[1]:""},setLocation:function(h){return window.location=h},_startPolling:function(j){var i=this;if(!Sammy.HashLocationProxy._interval){if(!j){j=10}var h=function(){current_location=i.getLocation();if(!Sammy.HashLocationProxy._last_location||current_location!=Sammy.HashLocationProxy._last_location){setTimeout(function(){g(window).trigger("hashchange")},1)}Sammy.HashLocationProxy._last_location=current_location};h();Sammy.HashLocationProxy._interval=setInterval(h,j);g(window).bind("unload",function(){clearInterval(Sammy.HashLocationProxy._interval)})}}};Sammy.DataLocationProxy=function(i,h){this.app=i;this.data_name=h||"sammy-location"};Sammy.DataLocationProxy.prototype={bind:function(){var h=this;this.app.$element().bind("setData",function(j,i){if(i==h.data_name){h.app.trigger("location-changed")}})},unbind:function(){this.app.$element().die("setData")},getLocation:function(){return this.app.$element().data(this.data_name)},setLocation:function(h){return this.app.$element().data(this.data_name,h)}};Sammy.Application=function(h){var i=this;this.routes={};this.listeners=new Sammy.Object({});this.arounds=[];this.befores=[];this.namespace=this.uuid();this.context_prototype=function(){Sammy.EventContext.apply(this,arguments)};this.context_prototype.prototype=new Sammy.EventContext();if(g.isFunction(h)){h.apply(this,[this])}if(!this.location_proxy){this.location_proxy=new Sammy.HashLocationProxy(i,this.run_interval_every)}if(this.debug){this.bindToAllEvents(function(k,j){i.log(i.toString(),k.cleaned_type,j||{})})}};Sammy.Application.prototype=g.extend({},Sammy.Object.prototype,{ROUTE_VERBS:["get","post","put","delete"],APP_EVENTS:["run","unload","lookup-route","run-route","route-found","event-context-before","event-context-after","changed","error-404","check-form-submission","redirect"],_last_route:null,_running:false,data_store_name:"sammy-app",element_selector:"body",debug:false,silence_404:true,run_interval_every:50,location_proxy:null,template_engine:null,toString:function(){return"Sammy.Application:"+this.element_selector},$element:function(){return g(this.element_selector)},use:function(){var h=g.makeArray(arguments);var i=h.shift();try{h.unshift(this);i.apply(this,h)}catch(j){if(typeof i=="undefined"){throw ("Error: called use() but plugin is not defined")}else{if(!g.isFunction(i)){throw ("Error: called use() but '"+i.toString()+"' is not a function")}else{throw (j)}}}return this},route:function(k,i,m){var j=this,l=[],h;if(!m&&g.isFunction(i)){i=k;m=i;k="any"}k=k.toLowerCase();if(i.constructor==String){f.lastIndex=0;while((path_match=f.exec(i))!=null){l.push(path_match[1])}i=new RegExp("^"+i.replace(f,d)+"$")}if(typeof m=="string"){m=j[m]}h=function(n){var o={verb:n,path:i,callback:m,param_names:l};j.routes[n]=j.routes[n]||[];j.routes[n].push(o)};if(k==="any"){g.each(this.ROUTE_VERBS,function(o,n){h(n)})}else{h(k)}return this},get:b("get"),post:b("post"),put:b("put"),del:b("delete"),any:b("any"),mapRoutes:function(i){var h=this;g.each(i,function(j,k){h.route.apply(h,k)});return this},eventNamespace:function(){return[this.data_store_name,this.namespace].join("-")},bind:function(h,j,l){var k=this;if(typeof l=="undefined"){l=j}var i=function(){var o,m,n;o=arguments[0];n=arguments[1];if(n&&n.context){m=n.context;delete n.context}else{m=new k.context_prototype(k,"bind",o.type,n)}o.cleaned_type=o.type.replace(k.eventNamespace(),"");l.apply(m,[o,n])};if(!this.listeners[h]){this.listeners[h]=[]}this.listeners[h].push(i);if(this.isRunning()){this._listen(h,i)}return this},trigger:function(h,i){this.$element().trigger([h,this.eventNamespace()].join("."),[i]);return this},refresh:function(){this.last_location=null;this.trigger("location-changed");return this},before:function(h,i){if(g.isFunction(h)){i=h;h={}}this.befores.push([h,i]);return this},after:function(h){return this.bind("event-context-after",h)},around:function(h){this.arounds.push(h);return this},isRunning:function(){return this._running},helpers:function(h){g.extend(this.context_prototype.prototype,h);return this},helper:function(h,i){this.context_prototype.prototype[h]=i;return this},run:function(h){if(this.isRunning()){return false}var i=this;g.each(this.listeners.toHash(),function(j,k){g.each(k,function(m,l){i._listen(j,l)})});this.trigger("run",{start_url:h});this._running=true;this.$element().data(this.data_store_name,this);this.last_location=null;if(this.getLocation()==""&&typeof h!="undefined"){this.setLocation(h)}this._checkLocation();this.location_proxy.bind();this.bind("location-changed",function(){i._checkLocation()});this.bind("submit",function(k){var j=i._checkFormSubmission(g(k.target).closest("form"));return(j===false)?k.preventDefault():false});g("body").bind("onunload",function(){i.unload()});return this.trigger("changed")},unload:function(){if(!this.isRunning()){return false}var h=this;this.trigger("unload");this.location_proxy.unbind();this.$element().unbind("submit").removeClass(h.eventNamespace());this.$element().removeData(this.data_store_name);g.each(this.listeners.toHash(),function(i,j){g.each(j,function(l,k){h._unlisten(i,k)})});this._running=false;return this},bindToAllEvents:function(i){var h=this;g.each(this.APP_EVENTS,function(j,k){h.bind(k,i)});g.each(this.listeners.keys(true),function(k,j){if(h.APP_EVENTS.indexOf(j)==-1){h.bind(j,i)}});return this},routablePath:function(h){return h.replace(c,"")},lookupRoute:function(k,i){var j=this,h=false;this.trigger("lookup-route",{verb:k,path:i});if(typeof this.routes[k]!="undefined"){g.each(this.routes[k],function(m,l){if(j.routablePath(i).match(l.path)){h=l;return false}})}return h},runRoute:function(i,r,k){this.log("runRoute",[i,r].join(" "));this.trigger("run-route",{verb:i,path:r,params:k});if(typeof k=="undefined"){k={}}g.extend(k,this._parseQueryString(r));var j=this,h,n,l,m,q,o,p=this.lookupRoute(i,r);if(p){this.trigger("route-found",{route:p});if((path_params=p.path.exec(this.routablePath(r)))!=null){path_params.shift();g.each(path_params,function(s,t){if(p.param_names[s]){k[p.param_names[s]]=a(t)}else{if(!k.splat){k.splat=[]}k.splat.push(a(t))}})}h=new this.context_prototype(this,i,r,k);l=this.arounds.slice(0);q=this.befores.slice(0);n=function(){var s;while(q.length>0){o=q.shift();if(j.contextMatchesOptions(h,o[0])){s=o[1].apply(h,[h]);if(s===false){return false}}}j.last_route=p;h.trigger("event-context-before",{context:h});s=p.callback.apply(h,[h]);h.trigger("event-context-after",{context:h});return s};g.each(l.reverse(),function(s,t){var u=n;n=function(){return t.apply(h,[u])}});return n()}else{this.notFound(i,r)}},contextMatchesOptions:function(k,m,i){var j=m;if(typeof j==="undefined"||j=={}){return true}if(typeof i==="undefined"){i=true}if(typeof j==="string"||g.isFunction(j.test)){j={path:j}}if(j.only){return this.contextMatchesOptions(k,j.only,true)}else{if(j.except){return this.contextMatchesOptions(k,j.except,false)}}var h=true,l=true;if(j.path){if(g.isFunction(j.path.test)){h=j.path.test(k.path)}else{h=(j.path.toString()===k.path)}}if(j.verb){l=j.verb===k.verb}return i?(l&&h):!(l&&h)},getLocation:function(){return this.location_proxy.getLocation()},setLocation:function(h){return this.location_proxy.setLocation(h)},swap:function(h){return this.$element().html(h)},notFound:function(i,h){this.trigger("error-404",{verb:i,path:h});throw ("404 Not Found "+i+" "+h)},_checkLocation:function(){try{var h,i;h=this.getLocation();if(h!=this.last_location){i=this.runRoute("get",h)}this.last_location=h}catch(j){this.last_location=h;if(j.toString().match(/^404/)&&this.silence_404){return i}else{throw (j)}}return i},_checkFormSubmission:function(j){var h,l,n,m,i;this.trigger("check-form-submission",{form:j});h=g(j);l=h.attr("action");n=g.trim(h.attr("method").toString().toLowerCase());if(!n||n==""){n="get"}this.log("_checkFormSubmission",h,l,n);m=g.extend({},this._parseFormParams(h),{"$form":h});try{i=this.runRoute(n,l,m)}catch(k){if(k.toString().match(/^404/)&&this.silence_404){return true}else{throw (k)}}return(typeof i=="undefined")?false:i},_parseFormParams:function(h){var i={};g.each(h.serializeArray(),function(j,k){if(i[k.name]){if(g.isArray(i[k.name])){i[k.name].push(k.value)}else{i[k.name]=[i[k.name],k.value]}}else{i[k.name]=k.value}});return i},_parseQueryString:function(m){var k={},l,j,n,h;l=m.match(c);if(l){j=l[1].split("&");for(h=0;h<j.length;h+=1){n=j[h].split("=");k[n[0]]=a(n[1])}}return k},_listen:function(h,i){return this.$element().bind([h,this.eventNamespace()].join("."),i)},_unlisten:function(h,i){return this.$element().unbind([h,this.eventNamespace()].join("."),i)}});Sammy.EventContext=function(k,j,h,i){this.app=k;this.verb=j;this.path=h;this.params=new Sammy.Object(i)};Sammy.EventContext.prototype=g.extend({},Sammy.Object.prototype,{$element:function(){return this.app.$element()},partial:function(p,l,o){var h,k,n,m,j="partial:"+p,i=this;if((n=p.match(/\.([^\.]+)$/))){n=n[1]}if((!n||!g.isFunction(i[n]))&&this.app.template_engine){n=this.app.template_engine}if(n&&!g.isFunction(n)&&g.isFunction(i[n])){n=i[n]}if(!o&&g.isFunction(l)){o=l;l={}}m=(g.isArray(l)?l:[l||{}]),k=function(q){var r=q,s="";g.each(m,function(t,u){g.extend(u,i);if(g.isFunction(n)){r=n.apply(i,[q,u])}s+=r;if(o){return o.apply(i,[r,t])}});if(!o){i.app.swap(s)}i.trigger("changed")};if(this.app.cache_partials&&this.cache(j)){k.apply(i,[this.cache(j)])}else{g.get(p,function(q){if(i.app.cache_partials){i.cache(j,q)}k.apply(i,[q])})}},redirect:function(){var j,i=g.makeArray(arguments),h=this.app.getLocation();if(i.length>1){i.unshift("/");j=this.join.apply(this,i)}else{j=i[0]}this.trigger("redirect",{to:j});this.app.last_location=this.path;this.app.setLocation(j);if(h==j){this.app.trigger("location-changed")}},trigger:function(h,i){if(typeof i=="undefined"){i={}}if(!i.context){i.context=this}return this.app.trigger(h,i)},eventNamespace:function(){return this.app.eventNamespace()},notFound:function(){return this.app.notFound(this.verb,this.path)},toString:function(){return"Sammy.EventContext: "+[this.verb,this.path,this.params].join(" ")}});g.sammy=Sammy})(jQuery);
|