discussion 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +16 -0
  3. data/Rakefile +40 -0
  4. data/app/assets/javascripts/discussion/application.js +1 -0
  5. data/app/assets/javascripts/discussion/discussion.js +28 -0
  6. data/app/assets/stylesheets/discussion/application.css +13 -0
  7. data/app/assets/stylesheets/discussion/threads.css +4 -0
  8. data/app/assets/stylesheets/scaffold.css +56 -0
  9. data/app/controllers/discussion/application_controller.rb +4 -0
  10. data/app/controllers/discussion/comments_controller.rb +100 -0
  11. data/app/controllers/discussion/threads_controller.rb +128 -0
  12. data/app/helpers/discussion/application_helper.rb +9 -0
  13. data/app/helpers/discussion/comments_helper.rb +20 -0
  14. data/app/helpers/discussion/threads_helper.rb +52 -0
  15. data/app/models/discussion/comment.rb +54 -0
  16. data/app/models/discussion/comment_read.rb +27 -0
  17. data/app/models/discussion/concerns.rb +24 -0
  18. data/app/models/discussion/thread.rb +69 -0
  19. data/app/models/discussion/thread_read.rb +9 -0
  20. data/app/models/thread_sweeper.rb +23 -0
  21. data/app/views/discussion/comments/_form.html.erb +1 -0
  22. data/app/views/discussion/comments/_list_with_form.html.erb +10 -0
  23. data/app/views/discussion/comments/_view.html.erb +3 -0
  24. data/app/views/discussion/comments/create.js.erb +2 -0
  25. data/app/views/discussion/comments/index.js.erb +2 -0
  26. data/app/views/discussion/threads/_form.html.erb +16 -0
  27. data/app/views/discussion/threads/_index.html.erb +5 -0
  28. data/app/views/discussion/threads/_list.html.erb +40 -0
  29. data/app/views/discussion/threads/_view.html.erb +13 -0
  30. data/app/views/discussion/threads/create.js.erb +2 -0
  31. data/app/views/discussion/threads/index.html.erb +3 -0
  32. data/app/views/discussion/threads/index.js.erb +2 -0
  33. data/app/views/discussion/threads/list.html.erb +1 -0
  34. data/app/views/discussion/threads/new.html.erb +1 -0
  35. data/app/views/discussion/threads/new.js.erb +2 -0
  36. data/app/views/discussion/threads/show.html.erb +1 -0
  37. data/app/views/discussion/threads/show.js.erb +2 -0
  38. data/config/routes.rb +5 -0
  39. data/db/migrate/20130501074817_create_discussion_threads.rb +14 -0
  40. data/db/migrate/20130501075956_create_discussion_concerns.rb +13 -0
  41. data/db/migrate/20130501080150_create_discussion_comments.rb +15 -0
  42. data/db/migrate/20130501080604_create_discussion_comment_reads.rb +11 -0
  43. data/db/migrate/20130502121352_create_discussion_thread_reads.rb +13 -0
  44. data/db/migrate/20130509100700_add_topic_to_threads.rb +9 -0
  45. data/lib/discussion.rb +15 -0
  46. data/lib/discussion/engine.rb +10 -0
  47. data/lib/discussion/version.rb +3 -0
  48. data/lib/generators/discussion/USAGE +15 -0
  49. data/lib/generators/discussion/discussion_generator.rb +26 -0
  50. data/lib/tasks/discussion_tasks.rake +4 -0
  51. data/test/discussion_test.rb +7 -0
  52. data/test/dummy/README.rdoc +261 -0
  53. data/test/dummy/Rakefile +7 -0
  54. data/test/dummy/app/assets/javascripts/application.js +4 -0
  55. data/test/dummy/app/assets/javascripts/assignments.js +2 -0
  56. data/test/dummy/app/assets/stylesheets/application.css +28 -0
  57. data/test/dummy/app/assets/stylesheets/assignments.css +4 -0
  58. data/test/dummy/app/assets/stylesheets/scaffold.css +56 -0
  59. data/test/dummy/app/controllers/application_controller.rb +8 -0
  60. data/test/dummy/app/controllers/assignments_controller.rb +2 -0
  61. data/test/dummy/app/helpers/application_helper.rb +8 -0
  62. data/test/dummy/app/helpers/assignments_helper.rb +2 -0
  63. data/test/dummy/app/models/assignment.rb +5 -0
  64. data/test/dummy/app/models/user.rb +9 -0
  65. data/test/dummy/app/views/assignments/_form.html.erb +29 -0
  66. data/test/dummy/app/views/assignments/edit.html.erb +6 -0
  67. data/test/dummy/app/views/assignments/index.html.erb +27 -0
  68. data/test/dummy/app/views/assignments/new.html.erb +5 -0
  69. data/test/dummy/app/views/assignments/show.html.erb +32 -0
  70. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  71. data/test/dummy/app/views/layouts/discussion/application.html.erb +14 -0
  72. data/test/dummy/config.ru +4 -0
  73. data/test/dummy/config/application.rb +58 -0
  74. data/test/dummy/config/boot.rb +10 -0
  75. data/test/dummy/config/database.yml +25 -0
  76. data/test/dummy/config/environment.rb +5 -0
  77. data/test/dummy/config/environments/development.rb +52 -0
  78. data/test/dummy/config/environments/production.rb +67 -0
  79. data/test/dummy/config/environments/test.rb +37 -0
  80. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  81. data/test/dummy/config/initializers/inflections.rb +15 -0
  82. data/test/dummy/config/initializers/mime_types.rb +5 -0
  83. data/test/dummy/config/initializers/secret_token.rb +7 -0
  84. data/test/dummy/config/initializers/session_store.rb +8 -0
  85. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  86. data/test/dummy/config/locales/en.yml +5 -0
  87. data/test/dummy/config/routes.rb +9 -0
  88. data/test/dummy/custom_plan.rb +11 -0
  89. data/test/dummy/db/development.sqlite3 +0 -0
  90. data/test/dummy/db/migrate/20120624033524_devise_create_users.rb +53 -0
  91. data/test/dummy/db/migrate/20130501154800_create_discussion_threads.discussion.rb +15 -0
  92. data/test/dummy/db/migrate/20130501154801_create_discussion_concerns.discussion.rb +14 -0
  93. data/test/dummy/db/migrate/20130501154802_create_discussion_comments.discussion.rb +16 -0
  94. data/test/dummy/db/migrate/20130501154803_create_discussion_comment_reads.discussion.rb +12 -0
  95. data/test/dummy/db/migrate/20130502144148_create_discussion_thread_reads.discussion.rb +14 -0
  96. data/test/dummy/db/migrate/20130509101316_create_assignments.rb +12 -0
  97. data/test/dummy/db/migrate/20130509101334_add_topic_to_threads.discussion.rb +10 -0
  98. data/test/dummy/db/schema.rb +104 -0
  99. data/test/dummy/db/seed.rb +28 -0
  100. data/test/dummy/db/test.sqlite3 +0 -0
  101. data/test/dummy/log/development.log +9981 -0
  102. data/test/dummy/public/404.html +26 -0
  103. data/test/dummy/public/422.html +26 -0
  104. data/test/dummy/public/500.html +25 -0
  105. data/test/dummy/public/favicon.ico +0 -0
  106. data/test/dummy/script/rails +6 -0
  107. data/test/dummy/spec/controllers/assignments_controller_spec.rb +160 -0
  108. data/test/dummy/spec/helpers/assignments_helper_spec.rb +15 -0
  109. data/test/dummy/spec/models/assignment_spec.rb +5 -0
  110. data/test/dummy/spec/requests/assignments_spec.rb +11 -0
  111. data/test/dummy/spec/routing/assignments_routing_spec.rb +35 -0
  112. data/test/dummy/spec/views/assignments/edit.html.erb_spec.rb +22 -0
  113. data/test/dummy/spec/views/assignments/index.html.erb_spec.rb +26 -0
  114. data/test/dummy/spec/views/assignments/new.html.erb_spec.rb +22 -0
  115. data/test/dummy/spec/views/assignments/show.html.erb_spec.rb +19 -0
  116. data/test/dummy/tmp/cache/34A/041/http%3A%2F%2Flocalhost%3A3000%2Fassets%2Fjquery.js%3Fbody%3D1 +0 -0
  117. data/test/dummy/tmp/cache/458/621/http%3A%2F%2Flocalhost%3A3000%2Fassets%2Fscaffold.css%3Fbody%3D1 +0 -0
  118. data/test/dummy/tmp/cache/4FB/6C1/http%3A%2F%2Flocalhost%3A3000%2Fassets%2Fjquery_ujs.js%3Fbody%3D1 +0 -0
  119. data/test/dummy/tmp/cache/53E/311/http%3A%2F%2Flocalhost%3A3000%2Fassets%2Fapplication.js%3Fbody%3D1 +0 -0
  120. data/test/dummy/tmp/cache/556/F41/http%3A%2F%2Flocalhost%3A3000%2Fassets%2Fassignments.js%3Fbody%3D1 +0 -0
  121. data/test/dummy/tmp/cache/5AA/581/http%3A%2F%2Flocalhost%3A3000%2Fassets%2Fapplication.css%3Fbody%3D1 +0 -0
  122. data/test/dummy/tmp/cache/5C2/331/http%3A%2F%2Flocalhost%3A3000%2Fassets%2Fassignments.css%3Fbody%3D1 +0 -0
  123. data/test/dummy/tmp/cache/9A9/BB0/total_unread_thread_by_6 +1 -0
  124. data/test/dummy/tmp/cache/9CF/491/http%3A%2F%2Flocalhost%3A3000%2Fassets%2Fdiscussion%2Fdiscussion.js%3Fbody%3D1 +0 -0
  125. data/test/dummy/tmp/cache/A1F/311/http%3A%2F%2Flocalhost%3A3000%2Fassets%2Fdiscussion%2Fapplication.js%3Fbody%3D1 +0 -0
  126. data/test/dummy/tmp/cache/A44/EA0/2898ba2093d346f7463a4396e46d4bd73590fd60 +25 -0
  127. data/test/dummy/tmp/cache/A53/930/8ab0f4219a7b2c19044a090115a45e76e43b268e +6 -0
  128. data/test/dummy/tmp/cache/A91/340/3f3d2d8955322f325af6db2238355fa07007ebd9 +5 -0
  129. data/test/dummy/tmp/cache/A9B/580/326f111948a98b94ce79f7ead20a6a8f6134316a +17 -0
  130. data/test/dummy/tmp/cache/ACB/1C0/61e9711fd55eccdf62882cb8d127b22664f7023f +4 -0
  131. data/test/dummy/tmp/cache/ACB/C60/2d70f6e0b599912c0a0a476f7d1d873d16fc587a +15 -0
  132. data/test/dummy/tmp/cache/AEF/AF0/24b5ae4d0aa3c3e6f7898cc323c8434330bf6c48 +20 -0
  133. data/test/dummy/tmp/cache/AF9/0E0/96b52cbbdd9b2500e89198a5d9ac461e490d2d27 +30 -0
  134. data/test/dummy/tmp/cache/B06/3F0/da9f60ff5af114f8058d98986d9c2350fd2df114 +9599 -0
  135. data/test/dummy/tmp/cache/B1C/810/9e06e1eec0d1350714a34d137eb4e4e93df71d7b +19 -0
  136. data/test/dummy/tmp/cache/B21/980/93de869eb331c65cb1c7a282ae089ee1b9111fd1 +25 -0
  137. data/test/dummy/tmp/cache/B27/910/da39a3ee5e6b4b0d3255bfef95601890afd80709 +0 -0
  138. data/test/dummy/tmp/cache/B30/970/7c338ed2840d2bf55f9f5e4eed04f66c80840eb3 +4 -0
  139. data/test/dummy/tmp/cache/B52/020/723598e1e44b35d4f2dca9ba0d3d1fa86fb63c81 +17 -0
  140. data/test/dummy/tmp/cache/B69/300/03c05703ee2f7ecbe9331dabc80cb14364ae1cd4 +14 -0
  141. data/test/dummy/tmp/cache/B72/C30/6c7fd8edb7af04528edf3f4c189f498ef511349e +20 -0
  142. data/test/dummy/tmp/cache/B8A/9B0/8446a97c4cbd4f1c6650b6dda8f7381cacfe5f31 +57 -0
  143. data/test/dummy/tmp/cache/BDA/810/586d7c0cfc531f2d9bffa4afa518cdde00e640a5 +25 -0
  144. data/test/dummy/tmp/cache/BE1/FA0/cef8de7e145c5aba7808de00a8b78750bfeba3b4 +30 -0
  145. data/test/dummy/tmp/cache/C0F/F10/853eabd960e1d1c97f280dfde98cda31aceda31c +401 -0
  146. data/test/dummy/tmp/cache/C41/FC0/b5dff9ef4aa8e34a09fbc8bc024f3ddd59d711ba +17 -0
  147. data/test/dummy/tmp/cache/assets/C80/A60/sprockets%2F3d71727f9a9628e5ea4071de13513523 +0 -0
  148. data/test/dummy/tmp/cache/assets/C8C/B80/sprockets%2F371bf96e99717688ed7313a0c53f4212 +0 -0
  149. data/test/dummy/tmp/cache/assets/CBB/080/sprockets%2F2d799cd88730be6f8d442356020b671f +0 -0
  150. data/test/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
  151. data/test/dummy/tmp/cache/assets/CE3/D10/sprockets%2F966d9544f2171c807e5dd194302de1cc +0 -0
  152. data/test/dummy/tmp/cache/assets/CEE/900/sprockets%2Fa62a39d06b7d4de441784b9974f92e52 +0 -0
  153. data/test/dummy/tmp/cache/assets/CF0/1D0/sprockets%2F6fc757c2c8329244ca95d6909865bbc2 +0 -0
  154. data/test/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
  155. data/test/dummy/tmp/cache/assets/D34/9E0/sprockets%2F11dabe8b1273c07cacd98060623de865 +0 -0
  156. data/test/dummy/tmp/cache/assets/D40/4E0/sprockets%2F441fdbbb1185dcb64934067f3a64f85e +0 -0
  157. data/test/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
  158. data/test/dummy/tmp/cache/assets/D59/650/sprockets%2F0e15e6c08b5d2c6fc092a5a804f1a4a2 +0 -0
  159. data/test/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
  160. data/test/dummy/tmp/cache/assets/D69/160/sprockets%2Fd50935d69817529b1cb6e6cadc111aec +0 -0
  161. data/test/dummy/tmp/cache/assets/D6C/290/sprockets%2Fedf363ea932d74107ecad71304e3c69d +0 -0
  162. data/test/dummy/tmp/cache/assets/D6D/870/sprockets%2F0b22785b6eb9daa3c9480e70771b6bed +0 -0
  163. data/test/dummy/tmp/cache/assets/D81/A20/sprockets%2F7fe1c5ae586747d5bba86892a2df7f42 +0 -0
  164. data/test/dummy/tmp/cache/assets/D92/C00/sprockets%2Fdd4af168d08e874f3d9c8e2d1f7d9898 +0 -0
  165. data/test/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
  166. data/test/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
  167. data/test/dummy/zeus.json +23 -0
  168. data/test/functional/discussion/threads_controller_test.rb +51 -0
  169. data/test/integration/navigation_test.rb +10 -0
  170. data/test/test_helper.rb +15 -0
  171. data/test/unit/discussion/comment_read_test.rb +9 -0
  172. data/test/unit/discussion/comment_test.rb +9 -0
  173. data/test/unit/discussion/concerns_test.rb +9 -0
  174. data/test/unit/discussion/thread_read_test.rb +9 -0
  175. data/test/unit/discussion/thread_test.rb +9 -0
  176. data/test/unit/helpers/discussion/threads_helper_test.rb +6 -0
  177. metadata +491 -0
@@ -0,0 +1,19 @@
1
+ o: ActiveSupport::Cache::Entry :@compressedF:@expires_in0:@created_atf1369580220.6274207: @value"[I"�var Disussion = {
2
+ loadComments: function (url, contrinerId) {
3
+ $ = jQuery;
4
+
5
+ $('#' + contrinerId).trigger('loading_comments');
6
+ console.log($('#' + contrinerId));
7
+ $.ajax({
8
+ url: url,
9
+ dataType: 'script',
10
+ data: {contrinerId: contrinerId},
11
+ type: 'GET'
12
+ }).done(function () {
13
+ $('#' + contrinerId).trigger('loaded_comments');
14
+ console.log($('#' + contrinerId));
15
+ });
16
+ }
17
+ }
18
+ ;
19
+ :EF
@@ -0,0 +1,25 @@
1
+ o: ActiveSupport::Cache::Entry :@compressedF:@expires_in0:@created_atf1369712587.1628125: @value"�[I"�var Disussion = {
2
+ loadComments: function (url, contrinerId) {
3
+ $ = jQuery;
4
+
5
+ $('body').on('loading_comments', '.comments_container', function (e) {
6
+ alert('loading_comments');
7
+ });
8
+
9
+ $('#' + contrinerId).trigger('loading_comments');
10
+ $('body').trigger('loading_comments');
11
+
12
+ console.log($('#' + contrinerId));
13
+ $.ajax({
14
+ url: url,
15
+ dataType: 'script',
16
+ data: {contrinerId: contrinerId},
17
+ type: 'GET'
18
+ }).done(function () {
19
+ $('#' + contrinerId).trigger('loaded_comments');
20
+ console.log($('#' + contrinerId));
21
+ });
22
+ }
23
+ }
24
+ ;
25
+ :EF
@@ -0,0 +1,4 @@
1
+ o: ActiveSupport::Cache::Entry :@compressedF:@expires_in0:@created_atf1369575133.4592059: @value"[I"
2
+
3
+
4
+ :EF
@@ -0,0 +1,17 @@
1
+ o: ActiveSupport::Cache::Entry :@compressedF:@expires_in0:@created_atf1369712802.9413733: @value"�[I"�var Disussion = {
2
+ loadComments: function (url, contrinerId) {
3
+ $ = jQuery;
4
+ $('#' + contrinerId).trigger('loading_comments');
5
+ $.ajax({
6
+ url: url,
7
+ dataType: 'script',
8
+ data: {contrinerId: contrinerId},
9
+ type: 'GET'
10
+ }).done(function () {
11
+ $('#' + contrinerId).trigger('loaded_comments');
12
+ console.log($('#' + contrinerId));
13
+ });
14
+ }
15
+ }
16
+ ;
17
+ :EF
@@ -0,0 +1,14 @@
1
+ o: ActiveSupport::Cache::Entry :@compressedF:@expires_in0:@created_atf1369575133.3689861: @value"&[I"var Disussion = {
2
+ loadComments: function (url, contrinerId) {
3
+ jQuery
4
+ .
5
+ ajax({
6
+ url: url,
7
+ dataType: 'script',
8
+ data: {contrinerId: contrinerId},
9
+ type: 'GET'
10
+ });
11
+ }
12
+ }
13
+ ;
14
+ :EF
@@ -0,0 +1,20 @@
1
+ o: ActiveSupport::Cache::Entry :@compressedF:@expires_in0:@created_atf1369712744.8485453: @value"[I"�var Disussion = {
2
+ loadComments: function (url, contrinerId) {
3
+ $ = jQuery;
4
+
5
+ $('#' + contrinerId).trigger('loading_comments');
6
+
7
+ console.log($('#' + contrinerId));
8
+ $.ajax({
9
+ url: url,
10
+ dataType: 'script',
11
+ data: {contrinerId: contrinerId},
12
+ type: 'GET'
13
+ }).done(function () {
14
+ $('#' + contrinerId).trigger('loaded_comments');
15
+ console.log($('#' + contrinerId));
16
+ });
17
+ }
18
+ }
19
+ ;
20
+ :EF
@@ -0,0 +1,57 @@
1
+ o: ActiveSupport::Cache::Entry :@compressedF:@expires_in0:@created_atf1369321743.5790932: @value"�[I"�body { background-color: #fff; color: #333; }
2
+
3
+ body, p, ol, ul, td {
4
+ font-family: verdana, arial, helvetica, sans-serif;
5
+ font-size: 13px;
6
+ line-height: 18px;
7
+ }
8
+
9
+ pre {
10
+ background-color: #eee;
11
+ padding: 10px;
12
+ font-size: 11px;
13
+ }
14
+
15
+ a { color: #000; }
16
+ a:visited { color: #666; }
17
+ a:hover { color: #fff; background-color:#000; }
18
+
19
+ div.field, div.actions {
20
+ margin-bottom: 10px;
21
+ }
22
+
23
+ #notice {
24
+ color: green;
25
+ }
26
+
27
+ .field_with_errors {
28
+ padding: 2px;
29
+ background-color: red;
30
+ display: table;
31
+ }
32
+
33
+ #error_explanation {
34
+ width: 450px;
35
+ border: 2px solid red;
36
+ padding: 7px;
37
+ padding-bottom: 0;
38
+ margin-bottom: 20px;
39
+ background-color: #f0f0f0;
40
+ }
41
+
42
+ #error_explanation h2 {
43
+ text-align: left;
44
+ font-weight: bold;
45
+ padding: 5px 5px 5px 15px;
46
+ font-size: 12px;
47
+ margin: -7px;
48
+ margin-bottom: 0px;
49
+ background-color: #c00;
50
+ color: #fff;
51
+ }
52
+
53
+ #error_explanation ul li {
54
+ font-size: 12px;
55
+ list-style: square;
56
+ }
57
+ :EF
@@ -0,0 +1,25 @@
1
+ o: ActiveSupport::Cache::Entry :@compressedF:@expires_in0:@created_atf1369712642.4066107: @value"�[I"�var Disussion = {
2
+ loadComments: function (url, contrinerId) {
3
+ $ = jQuery;
4
+
5
+ // $('body').on('loading_comments', '.comments_container', function (e) {
6
+ // alert('loading_comments');
7
+ // });
8
+
9
+ $('#' + contrinerId).trigger('loading_comments');
10
+ $('body').trigger('loading_comments');
11
+
12
+ console.log($('#' + contrinerId));
13
+ $.ajax({
14
+ url: url,
15
+ dataType: 'script',
16
+ data: {contrinerId: contrinerId},
17
+ type: 'GET'
18
+ }).done(function () {
19
+ $('#' + contrinerId).trigger('loaded_comments');
20
+ console.log($('#' + contrinerId));
21
+ });
22
+ }
23
+ }
24
+ ;
25
+ :EF
@@ -0,0 +1,30 @@
1
+ o: ActiveSupport::Cache::Entry :@compressedF:@expires_in0:@created_atf1369321743.5684407: @value"�[I"�/*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+
12
+
13
+ */
14
+
15
+ .unread {
16
+ color: blue !important;
17
+ }
18
+
19
+ .unread .counter {
20
+ color: red !important;
21
+ }
22
+
23
+ .read {
24
+ color: #666666 !important;
25
+ }
26
+
27
+ .read .counter {
28
+ color: green !important;
29
+ }
30
+ :EF
@@ -0,0 +1,401 @@
1
+ o: ActiveSupport::Cache::Entry :@compressedF:@expires_in0:@created_atf1369487935.4077451: @value"?[I" ?(function($, undefined) {
2
+
3
+ /**
4
+ * Unobtrusive scripting adapter for jQuery
5
+ * https://github.com/rails/jquery-ujs
6
+ *
7
+ * Requires jQuery 1.7.0 or later.
8
+ *
9
+ * Released under the MIT license
10
+ *
11
+ */
12
+
13
+ // Cut down on the number if issues from people inadvertently including jquery_ujs twice
14
+ // by detecting and raising an error when it happens.
15
+ var alreadyInitialized = function() {
16
+ var events = $._data(document, 'events');
17
+ return events && events.click && $.grep(events.click, function(e) { return e.namespace === 'rails'; }).length;
18
+ }
19
+
20
+ if ( alreadyInitialized() ) {
21
+ $.error('jquery-ujs has already been loaded!');
22
+ }
23
+
24
+ // Shorthand to make it a little easier to call public rails functions from within rails.js
25
+ var rails;
26
+
27
+ $.rails = rails = {
28
+ // Link elements bound by jquery-ujs
29
+ linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote], a[data-disable-with]',
30
+
31
+ // Select elements bound by jquery-ujs
32
+ inputChangeSelector: 'select[data-remote], input[data-remote], textarea[data-remote]',
33
+
34
+ // Form elements bound by jquery-ujs
35
+ formSubmitSelector: 'form',
36
+
37
+ // Form input elements bound by jquery-ujs
38
+ formInputClickSelector: 'form input[type=submit], form input[type=image], form button[type=submit], form button:not([type])',
39
+
40
+ // Form input elements disabled during form submission
41
+ disableSelector: 'input[data-disable-with], button[data-disable-with], textarea[data-disable-with]',
42
+
43
+ // Form input elements re-enabled after form submission
44
+ enableSelector: 'input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled',
45
+
46
+ // Form required input elements
47
+ requiredInputSelector: 'input[name][required]:not([disabled]),textarea[name][required]:not([disabled])',
48
+
49
+ // Form file input elements
50
+ fileInputSelector: 'input[type=file]',
51
+
52
+ // Link onClick disable selector with possible reenable after remote submission
53
+ linkDisableSelector: 'a[data-disable-with]',
54
+
55
+ // Make sure that every Ajax request sends the CSRF token
56
+ CSRFProtection: function(xhr) {
57
+ var token = $('meta[name="csrf-token"]').attr('content');
58
+ if (token) xhr.setRequestHeader('X-CSRF-Token', token);
59
+ },
60
+
61
+ // Triggers an event on an element and returns false if the event result is false
62
+ fire: function(obj, name, data) {
63
+ var event = $.Event(name);
64
+ obj.trigger(event, data);
65
+ return event.result !== false;
66
+ },
67
+
68
+ // Default confirm dialog, may be overridden with custom confirm dialog in $.rails.confirm
69
+ confirm: function(message) {
70
+ return confirm(message);
71
+ },
72
+
73
+ // Default ajax function, may be overridden with custom function in $.rails.ajax
74
+ ajax: function(options) {
75
+ return $.ajax(options);
76
+ },
77
+
78
+ // Default way to get an element's href. May be overridden at $.rails.href.
79
+ href: function(element) {
80
+ return element.attr('href');
81
+ },
82
+
83
+ // Submits "remote" forms and links with ajax
84
+ handleRemote: function(element) {
85
+ var method, url, data, elCrossDomain, crossDomain, withCredentials, dataType, options;
86
+
87
+ if (rails.fire(element, 'ajax:before')) {
88
+ elCrossDomain = element.data('cross-domain');
89
+ crossDomain = elCrossDomain === undefined ? null : elCrossDomain;
90
+ withCredentials = element.data('with-credentials') || null;
91
+ dataType = element.data('type') || ($.ajaxSettings && $.ajaxSettings.dataType);
92
+
93
+ if (element.is('form')) {
94
+ method = element.attr('method');
95
+ url = element.attr('action');
96
+ data = element.serializeArray();
97
+ // memoized value from clicked submit button
98
+ var button = element.data('ujs:submit-button');
99
+ if (button) {
100
+ data.push(button);
101
+ element.data('ujs:submit-button', null);
102
+ }
103
+ } else if (element.is(rails.inputChangeSelector)) {
104
+ method = element.data('method');
105
+ url = element.data('url');
106
+ data = element.serialize();
107
+ if (element.data('params')) data = data + "&" + element.data('params');
108
+ } else {
109
+ method = element.data('method');
110
+ url = rails.href(element);
111
+ data = element.data('params') || null;
112
+ }
113
+
114
+ options = {
115
+ type: method || 'GET', data: data, dataType: dataType,
116
+ // stopping the "ajax:beforeSend" event will cancel the ajax request
117
+ beforeSend: function(xhr, settings) {
118
+ if (settings.dataType === undefined) {
119
+ xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script);
120
+ }
121
+ return rails.fire(element, 'ajax:beforeSend', [xhr, settings]);
122
+ },
123
+ success: function(data, status, xhr) {
124
+ element.trigger('ajax:success', [data, status, xhr]);
125
+ },
126
+ complete: function(xhr, status) {
127
+ element.trigger('ajax:complete', [xhr, status]);
128
+ },
129
+ error: function(xhr, status, error) {
130
+ element.trigger('ajax:error', [xhr, status, error]);
131
+ },
132
+ crossDomain: crossDomain
133
+ };
134
+
135
+ // There is no withCredentials for IE6-8 when
136
+ // "Enable native XMLHTTP support" is disabled
137
+ if (withCredentials) {
138
+ options.xhrFields = {
139
+ withCredentials: withCredentials
140
+ };
141
+ }
142
+
143
+ // Only pass url to `ajax` options if not blank
144
+ if (url) { options.url = url; }
145
+
146
+ var jqxhr = rails.ajax(options);
147
+ element.trigger('ajax:send', jqxhr);
148
+ return jqxhr;
149
+ } else {
150
+ return false;
151
+ }
152
+ },
153
+
154
+ // Handles "data-method" on links such as:
155
+ // <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a>
156
+ handleMethod: function(link) {
157
+ var href = rails.href(link),
158
+ method = link.data('method'),
159
+ target = link.attr('target'),
160
+ csrf_token = $('meta[name=csrf-token]').attr('content'),
161
+ csrf_param = $('meta[name=csrf-param]').attr('content'),
162
+ form = $('<form method="post" action="' + href + '"></form>'),
163
+ metadata_input = '<input name="_method" value="' + method + '" type="hidden" />';
164
+
165
+ if (csrf_param !== undefined && csrf_token !== undefined) {
166
+ metadata_input += '<input name="' + csrf_param + '" value="' + csrf_token + '" type="hidden" />';
167
+ }
168
+
169
+ if (target) { form.attr('target', target); }
170
+
171
+ form.hide().append(metadata_input).appendTo('body');
172
+ form.submit();
173
+ },
174
+
175
+ /* Disables form elements:
176
+ - Caches element value in 'ujs:enable-with' data store
177
+ - Replaces element text with value of 'data-disable-with' attribute
178
+ - Sets disabled property to true
179
+ */
180
+ disableFormElements: function(form) {
181
+ form.find(rails.disableSelector).each(function() {
182
+ var element = $(this), method = element.is('button') ? 'html' : 'val';
183
+ element.data('ujs:enable-with', element[method]());
184
+ element[method](element.data('disable-with'));
185
+ element.prop('disabled', true);
186
+ });
187
+ },
188
+
189
+ /* Re-enables disabled form elements:
190
+ - Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
191
+ - Sets disabled property to false
192
+ */
193
+ enableFormElements: function(form) {
194
+ form.find(rails.enableSelector).each(function() {
195
+ var element = $(this), method = element.is('button') ? 'html' : 'val';
196
+ if (element.data('ujs:enable-with')) element[method](element.data('ujs:enable-with'));
197
+ element.prop('disabled', false);
198
+ });
199
+ },
200
+
201
+ /* For 'data-confirm' attribute:
202
+ - Fires `confirm` event
203
+ - Shows the confirmation dialog
204
+ - Fires the `confirm:complete` event
205
+
206
+ Returns `true` if no function stops the chain and user chose yes; `false` otherwise.
207
+ Attaching a handler to the element's `confirm` event that returns a `falsy` value cancels the confirmation dialog.
208
+ Attaching a handler to the element's `confirm:complete` event that returns a `falsy` value makes this function
209
+ return false. The `confirm:complete` event is fired whether or not the user answered true or false to the dialog.
210
+ */
211
+ allowAction: function(element) {
212
+ var message = element.data('confirm'),
213
+ answer = false, callback;
214
+ if (!message) { return true; }
215
+
216
+ if (rails.fire(element, 'confirm')) {
217
+ answer = rails.confirm(message);
218
+ callback = rails.fire(element, 'confirm:complete', [answer]);
219
+ }
220
+ return answer && callback;
221
+ },
222
+
223
+ // Helper function which checks for blank inputs in a form that match the specified CSS selector
224
+ blankInputs: function(form, specifiedSelector, nonBlank) {
225
+ var inputs = $(), input, valueToCheck,
226
+ selector = specifiedSelector || 'input,textarea',
227
+ allInputs = form.find(selector);
228
+
229
+ allInputs.each(function() {
230
+ input = $(this);
231
+ valueToCheck = input.is('input[type=checkbox],input[type=radio]') ? input.is(':checked') : input.val();
232
+ // If nonBlank and valueToCheck are both truthy, or nonBlank and valueToCheck are both falsey
233
+ if (!valueToCheck === !nonBlank) {
234
+
235
+ // Don't count unchecked required radio if other radio with same name is checked
236
+ if (input.is('input[type=radio]') && allInputs.filter('input[type=radio]:checked[name="' + input.attr('name') + '"]').length) {
237
+ return true; // Skip to next input
238
+ }
239
+
240
+ inputs = inputs.add(input);
241
+ }
242
+ });
243
+ return inputs.length ? inputs : false;
244
+ },
245
+
246
+ // Helper function which checks for non-blank inputs in a form that match the specified CSS selector
247
+ nonBlankInputs: function(form, specifiedSelector) {
248
+ return rails.blankInputs(form, specifiedSelector, true); // true specifies nonBlank
249
+ },
250
+
251
+ // Helper function, needed to provide consistent behavior in IE
252
+ stopEverything: function(e) {
253
+ $(e.target).trigger('ujs:everythingStopped');
254
+ e.stopImmediatePropagation();
255
+ return false;
256
+ },
257
+
258
+ // find all the submit events directly bound to the form and
259
+ // manually invoke them. If anyone returns false then stop the loop
260
+ callFormSubmitBindings: function(form, event) {
261
+ var events = form.data('events'), continuePropagation = true;
262
+ if (events !== undefined && events['submit'] !== undefined) {
263
+ $.each(events['submit'], function(i, obj){
264
+ if (typeof obj.handler === 'function') return continuePropagation = obj.handler(event);
265
+ });
266
+ }
267
+ return continuePropagation;
268
+ },
269
+
270
+ // replace element's html with the 'data-disable-with' after storing original html
271
+ // and prevent clicking on it
272
+ disableElement: function(element) {
273
+ element.data('ujs:enable-with', element.html()); // store enabled state
274
+ element.html(element.data('disable-with')); // set to disabled state
275
+ element.bind('click.railsDisable', function(e) { // prevent further clicking
276
+ return rails.stopEverything(e);
277
+ });
278
+ },
279
+
280
+ // restore element to its original state which was disabled by 'disableElement' above
281
+ enableElement: function(element) {
282
+ if (element.data('ujs:enable-with') !== undefined) {
283
+ element.html(element.data('ujs:enable-with')); // set to old enabled state
284
+ // this should be element.removeData('ujs:enable-with')
285
+ // but, there is currently a bug in jquery which makes hyphenated data attributes not get removed
286
+ element.data('ujs:enable-with', false); // clean up cache
287
+ }
288
+ element.unbind('click.railsDisable'); // enable element
289
+ }
290
+
291
+ };
292
+
293
+ if (rails.fire($(document), 'rails:attachBindings')) {
294
+
295
+ $.ajaxPrefilter(function(options, originalOptions, xhr){ if ( !options.crossDomain ) { rails.CSRFProtection(xhr); }});
296
+
297
+ $(document).delegate(rails.linkDisableSelector, 'ajax:complete', function() {
298
+ rails.enableElement($(this));
299
+ });
300
+
301
+ $(document).delegate(rails.linkClickSelector, 'click.rails', function(e) {
302
+ var link = $(this), method = link.data('method'), data = link.data('params');
303
+ if (!rails.allowAction(link)) return rails.stopEverything(e);
304
+
305
+ if (link.is(rails.linkDisableSelector)) rails.disableElement(link);
306
+
307
+ if (link.data('remote') !== undefined) {
308
+ if ( (e.metaKey || e.ctrlKey) && (!method || method === 'GET') && !data ) { return true; }
309
+
310
+ var handleRemote = rails.handleRemote(link);
311
+ // response from rails.handleRemote() will either be false or a deferred object promise.
312
+ if (handleRemote === false) {
313
+ rails.enableElement(link);
314
+ } else {
315
+ handleRemote.error( function() { rails.enableElement(link); } );
316
+ }
317
+ return false;
318
+
319
+ } else if (link.data('method')) {
320
+ rails.handleMethod(link);
321
+ return false;
322
+ }
323
+ });
324
+
325
+ $(document).delegate(rails.inputChangeSelector, 'change.rails', function(e) {
326
+ var link = $(this);
327
+ if (!rails.allowAction(link)) return rails.stopEverything(e);
328
+
329
+ rails.handleRemote(link);
330
+ return false;
331
+ });
332
+
333
+ $(document).delegate(rails.formSubmitSelector, 'submit.rails', function(e) {
334
+ var form = $(this),
335
+ remote = form.data('remote') !== undefined,
336
+ blankRequiredInputs = rails.blankInputs(form, rails.requiredInputSelector),
337
+ nonBlankFileInputs = rails.nonBlankInputs(form, rails.fileInputSelector);
338
+
339
+ if (!rails.allowAction(form)) return rails.stopEverything(e);
340
+
341
+ // skip other logic when required values are missing or file upload is present
342
+ if (blankRequiredInputs && form.attr("novalidate") == undefined && rails.fire(form, 'ajax:aborted:required', [blankRequiredInputs])) {
343
+ return rails.stopEverything(e);
344
+ }
345
+
346
+ if (remote) {
347
+ if (nonBlankFileInputs) {
348
+ // slight timeout so that the submit button gets properly serialized
349
+ // (make it easy for event handler to serialize form without disabled values)
350
+ setTimeout(function(){ rails.disableFormElements(form); }, 13);
351
+ var aborted = rails.fire(form, 'ajax:aborted:file', [nonBlankFileInputs]);
352
+
353
+ // re-enable form elements if event bindings return false (canceling normal form submission)
354
+ if (!aborted) { setTimeout(function(){ rails.enableFormElements(form); }, 13); }
355
+
356
+ return aborted;
357
+ }
358
+
359
+ // If browser does not support submit bubbling, then this live-binding will be called before direct
360
+ // bindings. Therefore, we should directly call any direct bindings before remotely submitting form.
361
+ if (!$.support.submitBubbles && $().jquery < '1.7' && rails.callFormSubmitBindings(form, e) === false) return rails.stopEverything(e);
362
+
363
+ rails.handleRemote(form);
364
+ return false;
365
+
366
+ } else {
367
+ // slight timeout so that the submit button gets properly serialized
368
+ setTimeout(function(){ rails.disableFormElements(form); }, 13);
369
+ }
370
+ });
371
+
372
+ $(document).delegate(rails.formInputClickSelector, 'click.rails', function(event) {
373
+ var button = $(this);
374
+
375
+ if (!rails.allowAction(button)) return rails.stopEverything(event);
376
+
377
+ // register the pressed submit button
378
+ var name = button.attr('name'),
379
+ data = name ? {name:name, value:button.val()} : null;
380
+
381
+ button.closest('form').data('ujs:submit-button', data);
382
+ });
383
+
384
+ $(document).delegate(rails.formSubmitSelector, 'ajax:beforeSend.rails', function(event) {
385
+ if (this == event.target) rails.disableFormElements($(this));
386
+ });
387
+
388
+ $(document).delegate(rails.formSubmitSelector, 'ajax:complete.rails', function(event) {
389
+ if (this == event.target) rails.enableFormElements($(this));
390
+ });
391
+
392
+ $(function(){
393
+ // making sure that all forms have actual up-to-date token(cached forms contain old one)
394
+ var csrf_token = $('meta[name=csrf-token]').attr('content');
395
+ var csrf_param = $('meta[name=csrf-param]').attr('content');
396
+ $('form input[name="' + csrf_param + '"]').val(csrf_token);
397
+ });
398
+ }
399
+
400
+ })( jQuery );
401
+ :EF