jim 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/HISTORY +28 -0
  2. data/README.rdoc +1 -1
  3. data/Rakefile +2 -1
  4. data/jim.gemspec +67 -9
  5. data/lib/jim/bundler.rb +14 -11
  6. data/lib/jim/cli.rb +51 -9
  7. data/lib/jim/index.rb +3 -7
  8. data/lib/jim/installer.rb +140 -22
  9. data/lib/jim/templates/commands +21 -6
  10. data/lib/jim/version_parser.rb +2 -3
  11. data/lib/jim.rb +19 -2
  12. data/test/fixtures/jimfile +3 -3
  13. data/test/fixtures/sammy-0.5.0/HISTORY.md +135 -0
  14. data/test/fixtures/sammy-0.5.0/LICENSE +22 -0
  15. data/test/fixtures/sammy-0.5.0/README.md +81 -0
  16. data/test/fixtures/sammy-0.5.0/Rakefile +174 -0
  17. data/test/fixtures/sammy-0.5.0/examples/backend/README.md +23 -0
  18. data/test/fixtures/sammy-0.5.0/examples/backend/Rakefile +15 -0
  19. data/test/fixtures/sammy-0.5.0/examples/backend/app.rb +17 -0
  20. data/test/fixtures/sammy-0.5.0/examples/backend/app.ru +3 -0
  21. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/app.js +106 -0
  22. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.cloudkit.js +840 -0
  23. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.js +19 -0
  24. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/sammy.js +1013 -0
  25. data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/index.html.erb +11 -0
  26. data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task.html.erb +4 -0
  27. data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task_details.html.erb +4 -0
  28. data/test/fixtures/sammy-0.5.0/examples/backend/views/app.sass +63 -0
  29. data/test/fixtures/sammy-0.5.0/examples/backend/views/index.haml +18 -0
  30. data/test/fixtures/sammy-0.5.0/examples/form_handling/files/form.html +12 -0
  31. data/test/fixtures/sammy-0.5.0/examples/form_handling/index.html +65 -0
  32. data/test/fixtures/sammy-0.5.0/examples/hello_world/index.html +50 -0
  33. data/test/fixtures/sammy-0.5.0/examples/location_override/README.md +15 -0
  34. data/test/fixtures/sammy-0.5.0/examples/location_override/data.html +110 -0
  35. data/test/fixtures/sammy-0.5.0/examples/location_override/index.html +79 -0
  36. data/test/fixtures/sammy-0.5.0/examples/location_override/test.html +121 -0
  37. data/test/fixtures/sammy-0.5.0/lib/min/sammy-0.5.0.min.js +5 -0
  38. data/test/fixtures/sammy-0.5.0/lib/min/sammy-lastest.min.js +5 -0
  39. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.cache.js +117 -0
  40. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.haml.js +539 -0
  41. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.json.js +362 -0
  42. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.mustache.js +415 -0
  43. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.nested_params.js +118 -0
  44. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.storage.js +515 -0
  45. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.template.js +117 -0
  46. data/test/fixtures/sammy-0.5.0/lib/sammy.js +1367 -0
  47. data/test/fixtures/sammy-0.5.0/test/fixtures/partial +1 -0
  48. data/test/fixtures/sammy-0.5.0/test/fixtures/partial.html +1 -0
  49. data/test/fixtures/sammy-0.5.0/test/fixtures/partial.noengine +1 -0
  50. data/test/fixtures/sammy-0.5.0/test/fixtures/partial.template +1 -0
  51. data/test/fixtures/sammy-0.5.0/test/index.html +84 -0
  52. data/test/fixtures/sammy-0.5.0/test/test_sammy_application.js +953 -0
  53. data/test/fixtures/sammy-0.5.0/test/test_sammy_event_context.js +252 -0
  54. data/test/fixtures/sammy-0.5.0/test/test_sammy_location_proxy.js +91 -0
  55. data/test/fixtures/sammy-0.5.0/test/test_sammy_plugins.js +296 -0
  56. data/test/fixtures/sammy-0.5.0/test/test_sammy_storage.js +175 -0
  57. data/test/fixtures/sammy-0.5.0/test/test_server +27 -0
  58. data/test/fixtures/sammy-0.5.0/vendor/jquery-1.4.1.js +6078 -0
  59. data/test/fixtures/sammy-0.5.0/vendor/jquery-1.4.1.min.js +152 -0
  60. data/test/fixtures/sammy-0.5.0/vendor/jsdoc/doc.haml +58 -0
  61. data/test/fixtures/sammy-0.5.0/vendor/jsdoc/jsdoc.rb +143 -0
  62. data/test/fixtures/sammy-0.5.0/vendor/jslitmus.js +670 -0
  63. data/test/fixtures/sammy-0.5.0/vendor/qunit/qunit.css +119 -0
  64. data/test/fixtures/sammy-0.5.0/vendor/qunit/qunit.js +1043 -0
  65. data/test/fixtures/sammy-0.5.0/vendor/qunit-spec.js +127 -0
  66. data/test/helper.rb +23 -3
  67. data/test/test_jim_bundler.rb +9 -8
  68. data/test/test_jim_cli.rb +21 -12
  69. data/test/test_jim_installer.rb +152 -35
  70. data/test/test_jim_version_parser.rb +4 -0
  71. metadata +117 -27
  72. data/.document +0 -5
@@ -0,0 +1,11 @@
1
+ <ul id="tasks"></ul>
2
+ <div id="task_entry">
3
+ <form action="#/tasks" method="post">
4
+ <p>
5
+ <input class="entry" name="entry" type="text" />
6
+ </p>
7
+ <p>
8
+ <input type="submit" value="Create" />
9
+ </p>
10
+ </form>
11
+ </div>
@@ -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,4 @@
1
+ <%= console.log('template task', task) %>
2
+ <div id="task_<%= task.__id__ %>">
3
+ <h3><%= task.entry %></h3>
4
+ </div>
@@ -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 &rarr;"/></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 &rarr;"/></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 &rarr;"/></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);