jim 0.1.2 → 0.2.0
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.
- 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);
|