my_forum 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (203) hide show
  1. checksums.yaml +4 -4
  2. data/README.rdoc +12 -1
  3. data/Rakefile +4 -3
  4. data/{test/dummy/public/favicon.ico → app/assets/javascripts/my_forum/admin/categories.js.coffee} +0 -0
  5. data/app/assets/javascripts/my_forum/admin/dashboard.js.coffee +0 -0
  6. data/app/assets/javascripts/my_forum/admin/forums.js.coffee +0 -0
  7. data/app/assets/javascripts/my_forum/admin/roles.js +2 -0
  8. data/app/assets/javascripts/my_forum/admin/users.js +2 -0
  9. data/app/assets/javascripts/my_forum/application.js +6 -0
  10. data/app/assets/javascripts/my_forum/forums.js.coffee +0 -0
  11. data/app/assets/javascripts/my_forum/jquery.scrollTo.min.js +7 -0
  12. data/app/assets/javascripts/my_forum/jquery.selection.js +354 -0
  13. data/app/assets/javascripts/my_forum/my_forum.js.coffee +118 -0
  14. data/app/assets/javascripts/my_forum/posts.js.coffee +20 -0
  15. data/app/assets/javascripts/my_forum/topics.js.coffee +0 -0
  16. data/app/assets/javascripts/my_forum/users.js.coffee +0 -0
  17. data/app/assets/javascripts/my_forum/welcome.js.coffee +0 -0
  18. data/app/assets/stylesheets/my_forum/admin/categories.css.scss +0 -0
  19. data/app/assets/stylesheets/my_forum/admin/dashboard.css.scss +3 -0
  20. data/app/assets/stylesheets/my_forum/admin/forums.css.scss +7 -0
  21. data/app/assets/stylesheets/my_forum/admin/roles.css +4 -0
  22. data/app/assets/stylesheets/my_forum/admin/users.css +4 -0
  23. data/app/assets/stylesheets/my_forum/application.css.scss +80 -0
  24. data/app/assets/stylesheets/my_forum/forums.css.scss +31 -0
  25. data/app/assets/stylesheets/my_forum/posts.css.scss +138 -0
  26. data/app/assets/stylesheets/my_forum/private_messages.css.scss +11 -0
  27. data/app/assets/stylesheets/my_forum/topics.css.scss +16 -0
  28. data/app/assets/stylesheets/my_forum/users.css.scss +3 -0
  29. data/app/assets/stylesheets/my_forum/welcome.css.scss +73 -0
  30. data/app/controllers/my_forum/admin/categories_controller.rb +36 -0
  31. data/app/controllers/my_forum/admin/dashboard_controller.rb +13 -0
  32. data/app/controllers/my_forum/admin/emoticons_controller.rb +65 -0
  33. data/app/controllers/my_forum/admin/forums_controller.rb +35 -0
  34. data/app/controllers/my_forum/admin/mail_controller.rb +31 -0
  35. data/app/controllers/my_forum/admin/roles_controller.rb +38 -0
  36. data/app/controllers/my_forum/admin/users_controller.rb +14 -0
  37. data/app/controllers/my_forum/application_controller.rb +81 -0
  38. data/app/controllers/my_forum/attachments_controller.rb +30 -0
  39. data/app/controllers/my_forum/forums_controller.rb +39 -0
  40. data/app/controllers/my_forum/images_controller.rb +7 -0
  41. data/app/controllers/my_forum/posts_controller.rb +96 -0
  42. data/app/controllers/my_forum/private_messages_controller.rb +73 -0
  43. data/app/controllers/my_forum/topics_controller.rb +96 -0
  44. data/app/controllers/my_forum/users_controller.rb +145 -0
  45. data/app/controllers/my_forum/welcome_controller.rb +30 -0
  46. data/app/helpers/my_forum/admin/dashboard_helper.rb +4 -0
  47. data/app/helpers/my_forum/admin/forums_helper.rb +4 -0
  48. data/app/helpers/my_forum/admin/roles_helper.rb +4 -0
  49. data/app/helpers/my_forum/admin/users_helper.rb +4 -0
  50. data/app/helpers/my_forum/application_helper.rb +43 -0
  51. data/app/helpers/my_forum/emoticons_helper.rb +7 -0
  52. data/app/helpers/my_forum/forums_helper.rb +44 -0
  53. data/app/helpers/my_forum/posts_helper.rb +76 -0
  54. data/app/helpers/my_forum/private_messages_helper.rb +25 -0
  55. data/app/helpers/my_forum/topics_helper.rb +18 -0
  56. data/app/helpers/my_forum/users_helper.rb +33 -0
  57. data/app/helpers/my_forum/welcome_helper.rb +4 -0
  58. data/app/mailers/application_mailer.rb +4 -0
  59. data/app/mailers/my_forum/user_mailer.rb +31 -0
  60. data/app/models/my_forum/attachment.rb +12 -0
  61. data/app/models/my_forum/avatar.rb +11 -0
  62. data/app/models/my_forum/category.rb +7 -0
  63. data/app/models/my_forum/category_permission.rb +6 -0
  64. data/app/models/my_forum/emoticon.rb +6 -0
  65. data/app/models/my_forum/forum.rb +50 -0
  66. data/app/models/my_forum/image.rb +5 -0
  67. data/app/models/my_forum/log_read_mark.rb +4 -0
  68. data/app/models/my_forum/post.rb +26 -0
  69. data/app/models/my_forum/private_message.rb +8 -0
  70. data/app/models/my_forum/role.rb +6 -0
  71. data/app/models/my_forum/topic.rb +41 -0
  72. data/app/models/my_forum/user.rb +71 -0
  73. data/app/models/my_forum/user_group.rb +13 -0
  74. data/app/models/my_forum/user_group_link.rb +6 -0
  75. data/app/models/my_forum/user_roles.rb +6 -0
  76. data/app/views/layouts/mailer.html.erb +5 -0
  77. data/app/views/layouts/mailer.text.erb +1 -0
  78. data/app/views/layouts/my_forum/_guest_navbar.html.haml +4 -0
  79. data/app/views/layouts/my_forum/_user_navbar.html.haml +19 -0
  80. data/app/views/layouts/my_forum/admin_application.haml +29 -0
  81. data/app/views/layouts/my_forum/application.haml +23 -0
  82. data/app/views/my_forum/admin/categories/edit.haml +9 -0
  83. data/app/views/my_forum/admin/categories/new.haml +5 -0
  84. data/app/views/my_forum/admin/dashboard/index.haml +0 -0
  85. data/app/views/my_forum/admin/emoticons/edit.haml +4 -0
  86. data/app/views/my_forum/admin/emoticons/index.haml +15 -0
  87. data/app/views/my_forum/admin/emoticons/new.haml +5 -0
  88. data/app/views/my_forum/admin/forums/index.haml +47 -0
  89. data/app/views/my_forum/admin/forums/new.haml +6 -0
  90. data/app/views/my_forum/admin/mail/index.haml +9 -0
  91. data/app/views/my_forum/admin/roles/index.haml +12 -0
  92. data/app/views/my_forum/admin/roles/new.haml +22 -0
  93. data/app/views/my_forum/admin/users/index.haml +10 -0
  94. data/app/views/my_forum/forums/_topic_subject.html.haml +16 -0
  95. data/app/views/my_forum/forums/show.haml +29 -0
  96. data/app/views/my_forum/posts/edit.html.haml +31 -0
  97. data/app/views/my_forum/private_messages/_sidebar.haml +10 -0
  98. data/app/views/my_forum/private_messages/inbox.haml +26 -0
  99. data/app/views/my_forum/private_messages/new.haml +21 -0
  100. data/app/views/my_forum/private_messages/show.haml +10 -0
  101. data/app/views/my_forum/shared/_post_preview.haml +15 -0
  102. data/app/views/my_forum/shared/_upload_photo.haml +45 -0
  103. data/app/views/my_forum/shared/post_preview.js.coffee +4 -0
  104. data/app/views/my_forum/topics/_post.haml +29 -0
  105. data/app/views/my_forum/topics/_profile_popover.haml +47 -0
  106. data/app/views/my_forum/topics/_quick_answer.haml +34 -0
  107. data/app/views/my_forum/topics/_topic_header.haml +4 -0
  108. data/app/views/my_forum/topics/_user_info.haml +9 -0
  109. data/app/views/my_forum/topics/new.haml +38 -0
  110. data/app/views/my_forum/topics/show.haml +60 -0
  111. data/app/views/my_forum/user_mailer/custom_email.text.erb +1 -0
  112. data/app/views/my_forum/user_mailer/ping_from_post.haml +8 -0
  113. data/app/views/my_forum/user_mailer/ping_from_post.text.erb +6 -0
  114. data/app/views/my_forum/user_mailer/pm_notification.text.erb +6 -0
  115. data/app/views/my_forum/user_mailer/reset_password_email.haml +1 -0
  116. data/app/views/my_forum/user_mailer/reset_password_email.text.erb +1 -0
  117. data/app/views/my_forum/users/edit.haml +36 -0
  118. data/app/views/my_forum/users/forgot_password.haml +10 -0
  119. data/app/views/my_forum/users/new.haml +14 -0
  120. data/app/views/my_forum/users/signin.haml +14 -0
  121. data/app/views/my_forum/users/signout.haml +0 -0
  122. data/app/views/my_forum/welcome/index.haml +37 -0
  123. data/config/initializers/will_paginate.rb +24 -0
  124. data/config/locales/en.yml +68 -0
  125. data/config/locales/ru.yml +198 -0
  126. data/config/routes.rb +48 -0
  127. data/db/migrate/20141117122725_create_my_forum_forums.rb +12 -0
  128. data/db/migrate/20141117122742_create_my_forum_topics.rb +17 -0
  129. data/db/migrate/20141117122751_create_my_forum_posts.rb +11 -0
  130. data/db/migrate/20141118081021_create_my_forum_categories.rb +8 -0
  131. data/db/migrate/20141118131215_create_my_forum_users.rb +34 -0
  132. data/db/migrate/20141222094522_create_my_forum_roles.rb +10 -0
  133. data/db/migrate/20141222094538_create_my_forum_user_roles.rb +9 -0
  134. data/db/migrate/20150202115250_create_my_forum_log_read_marks.rb +10 -0
  135. data/db/migrate/20150215200453_create_my_forum_user_groups.rb +15 -0
  136. data/db/migrate/20150215204852_create_my_forum_user_group_links.rb +9 -0
  137. data/db/migrate/20150215212443_create_my_forum_category_permissions.rb +9 -0
  138. data/db/migrate/20150227210814_create_my_forum_private_messages.rb +16 -0
  139. data/db/migrate/20151012095554_create_my_forum_images.rb +12 -0
  140. data/db/migrate/20151218135729_add_is_deleted.rb +6 -0
  141. data/db/migrate/20151220121140_create_my_forum_emoticons.rb +10 -0
  142. data/db/migrate/20151221203243_my_forum_rename_user_avatar.rb +5 -0
  143. data/db/migrate/20151221205045_my_forum_change_user_avatar.rb +5 -0
  144. data/db/migrate/20160122202142_add_latest_post_info_for_topic.rb +24 -0
  145. data/db/migrate/20160210130805_add_indexes_for_topics.rb +7 -0
  146. data/db/migrate/20160214085201_add_edited_by_for_post.rb +5 -0
  147. data/lib/my_forum/engine.rb +31 -0
  148. data/lib/my_forum/version.rb +1 -1
  149. data/lib/tasks/my_forum_tasks.rake +155 -4
  150. data/spec/controllers/my_forum/admin/emoticons_controller_spec.rb +7 -0
  151. data/spec/controllers/my_forum/admin/mail_controller_spec.rb +7 -0
  152. data/spec/controllers/my_forum/private_messages_controller_spec.rb +7 -0
  153. data/spec/controllers/my_forum/users_controller_spec.rb +76 -0
  154. data/{test → spec}/dummy/README.rdoc +0 -0
  155. data/{test → spec}/dummy/Rakefile +0 -0
  156. data/{test → spec}/dummy/app/assets/javascripts/application.js +1 -1
  157. data/{app/assets/stylesheets/my_forum → spec/dummy/app/assets/stylesheets}/application.css +1 -1
  158. data/{test → spec}/dummy/app/controllers/application_controller.rb +0 -0
  159. data/{test → spec}/dummy/app/helpers/application_helper.rb +0 -0
  160. data/{test → spec}/dummy/app/views/layouts/application.html.erb +0 -0
  161. data/{test → spec}/dummy/bin/bundle +0 -0
  162. data/{test → spec}/dummy/bin/rails +0 -0
  163. data/{test → spec}/dummy/bin/rake +0 -0
  164. data/{test → spec}/dummy/config/application.rb +0 -0
  165. data/{test → spec}/dummy/config/boot.rb +0 -0
  166. data/{test → spec}/dummy/config/database.yml +0 -0
  167. data/{test → spec}/dummy/config/environment.rb +0 -0
  168. data/{test → spec}/dummy/config/environments/development.rb +0 -0
  169. data/{test → spec}/dummy/config/environments/production.rb +1 -1
  170. data/{test → spec}/dummy/config/environments/test.rb +1 -1
  171. data/{test → spec}/dummy/config/initializers/assets.rb +0 -0
  172. data/{test → spec}/dummy/config/initializers/backtrace_silencers.rb +0 -0
  173. data/{test → spec}/dummy/config/initializers/cookies_serializer.rb +0 -0
  174. data/{test → spec}/dummy/config/initializers/filter_parameter_logging.rb +0 -0
  175. data/{test → spec}/dummy/config/initializers/inflections.rb +0 -0
  176. data/{test → spec}/dummy/config/initializers/mime_types.rb +0 -0
  177. data/{test → spec}/dummy/config/initializers/session_store.rb +0 -0
  178. data/{test → spec}/dummy/config/initializers/wrap_parameters.rb +0 -0
  179. data/{test → spec}/dummy/config/locales/en.yml +0 -0
  180. data/{test → spec}/dummy/config/routes.rb +0 -0
  181. data/{test → spec}/dummy/config/secrets.yml +0 -0
  182. data/{test → spec}/dummy/config.ru +0 -0
  183. data/spec/dummy/db/development.sqlite3 +0 -0
  184. data/spec/dummy/db/schema.rb +159 -0
  185. data/spec/dummy/db/test.sqlite3 +0 -0
  186. data/spec/dummy/log/development.log +12 -0
  187. data/{test → spec}/dummy/public/404.html +0 -0
  188. data/{test → spec}/dummy/public/422.html +0 -0
  189. data/{test → spec}/dummy/public/500.html +0 -0
  190. data/spec/dummy/public/favicon.ico +0 -0
  191. data/spec/helpers/my_forum/posts_helper_spec.rb +24 -0
  192. data/spec/helpers/my_forum/private_messages_helper_spec.rb +17 -0
  193. data/spec/models/my_forum/emoticon_spec.rb +7 -0
  194. data/spec/models/my_forum/private_message_spec.rb +7 -0
  195. data/spec/models/my_forum/user_spec.rb +13 -0
  196. data/spec/rails_helper.rb +52 -0
  197. data/spec/spec_helper.rb +87 -0
  198. metadata +356 -83
  199. data/app/views/layouts/my_forum/application.html.erb +0 -14
  200. data/test/dummy/app/assets/stylesheets/application.css +0 -15
  201. data/test/integration/navigation_test.rb +0 -10
  202. data/test/my_forum_test.rb +0 -7
  203. data/test/test_helper.rb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2ec79af48419743a46cb08ceacde067a36d5c658
4
- data.tar.gz: 1b16082b7f8f5cd4ca953c80ecbfc7453a8bd642
3
+ metadata.gz: ee1ba421dcc871ea818bc90b35ad0ec9c0c0e74b
4
+ data.tar.gz: f08beb05ab8c50fe16c9a0fb40cd793a426a679d
5
5
  SHA512:
6
- metadata.gz: 69de62c7ab134078ab86b43becd29403e4df93687d1c5b474055b74c7d84dc998d671301ab98c448581593faeefb53e4c0e111024cd79442cbca458fca56e294
7
- data.tar.gz: b9603bae08aceb948915a1bf2f00f60386447eb4beb11d2b42fce1fa2c82fb051948d391ab2524d5263f20fa09c10c20ad64de2b5613740c0f34e1c6b302aa82
6
+ metadata.gz: 2c3b1e5edb986c2cb9247315cd3edf131776d1b7ffb242a674fb3040d028fee1e04a3b6307b6e39021c8e85ccb40a25f699a776a777b38ed8475f8f86dd7b05e
7
+ data.tar.gz: c54770fa9defa218db1581bf133b9ccb384615444ded4a803119edfb8e981b2842782f168adfbe3834a78d0a0f6fe62fdf5e11b588b599268f74e653d62bbd98
data/README.rdoc CHANGED
@@ -1,3 +1,14 @@
1
+ {<img src="https://travis-ci.org/vintyara/my_forum.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/vintyara/my_forum]
2
+
1
3
  = MyForum
2
4
 
3
- This project rocks and uses MIT-LICENSE.
5
+ This project rocks and uses MIT-LICENSE.
6
+
7
+ INSTALLATION
8
+ rake my_forum:install:migrations
9
+
10
+ For using existing User model, use somethink like this:
11
+
12
+ Create config/initializers/my_forum.rb with next content:
13
+ MyForum::Engine.use_custom_user_model = true
14
+ ...
data/Rakefile CHANGED
@@ -14,19 +14,20 @@ RDoc::Task.new(:rdoc) do |rdoc|
14
14
  rdoc.rdoc_files.include('lib/**/*.rb')
15
15
  end
16
16
 
17
- APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
17
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
18
18
  load 'rails/tasks/engine.rake'
19
19
 
20
20
 
21
21
 
22
22
  Bundler::GemHelper.install_tasks
23
23
 
24
- require 'rake/testtask'
24
+ require 'rspec/core'
25
+ require 'rspec/core/rake_task'
25
26
 
26
27
  Rake::TestTask.new(:test) do |t|
27
28
  t.libs << 'lib'
28
29
  t.libs << 'test'
29
- t.pattern = 'test/**/*_test.rb'
30
+ t.pattern = 'spec/**/*_spec.rb'
30
31
  t.verbose = false
31
32
  end
32
33
 
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -10,4 +10,10 @@
10
10
  // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
11
  // about supported directives.
12
12
  //
13
+ //= require jquery
14
+ //= require jquery_ujs
15
+ //= require bootstrap-sprockets
16
+ //= require bootstrap
17
+ //= jquery.selection.js
18
+ //= jquery.scrollTo.min.js
13
19
  //= require_tree .
File without changes
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Copyright (c) 2007-2015 Ariel Flesler - aflesler<a>gmail<d>com | http://flesler.blogspot.com
3
+ * Licensed under MIT
4
+ * @author Ariel Flesler
5
+ * @version 2.1.2
6
+ */
7
+ ;(function(f){"use strict";"function"===typeof define&&define.amd?define(["jquery"],f):"undefined"!==typeof module&&module.exports?module.exports=f(require("jquery")):f(jQuery)})(function($){"use strict";function n(a){return!a.nodeName||-1!==$.inArray(a.nodeName.toLowerCase(),["iframe","#document","html","body"])}function h(a){return $.isFunction(a)||$.isPlainObject(a)?a:{top:a,left:a}}var p=$.scrollTo=function(a,d,b){return $(window).scrollTo(a,d,b)};p.defaults={axis:"xy",duration:0,limit:!0};$.fn.scrollTo=function(a,d,b){"object"=== typeof d&&(b=d,d=0);"function"===typeof b&&(b={onAfter:b});"max"===a&&(a=9E9);b=$.extend({},p.defaults,b);d=d||b.duration;var u=b.queue&&1<b.axis.length;u&&(d/=2);b.offset=h(b.offset);b.over=h(b.over);return this.each(function(){function k(a){var k=$.extend({},b,{queue:!0,duration:d,complete:a&&function(){a.call(q,e,b)}});r.animate(f,k)}if(null!==a){var l=n(this),q=l?this.contentWindow||window:this,r=$(q),e=a,f={},t;switch(typeof e){case "number":case "string":if(/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(e)){e= h(e);break}e=l?$(e):$(e,q);case "object":if(e.length===0)return;if(e.is||e.style)t=(e=$(e)).offset()}var v=$.isFunction(b.offset)&&b.offset(q,e)||b.offset;$.each(b.axis.split(""),function(a,c){var d="x"===c?"Left":"Top",m=d.toLowerCase(),g="scroll"+d,h=r[g](),n=p.max(q,c);t?(f[g]=t[m]+(l?0:h-r.offset()[m]),b.margin&&(f[g]-=parseInt(e.css("margin"+d),10)||0,f[g]-=parseInt(e.css("border"+d+"Width"),10)||0),f[g]+=v[m]||0,b.over[m]&&(f[g]+=e["x"===c?"width":"height"]()*b.over[m])):(d=e[m],f[g]=d.slice&& "%"===d.slice(-1)?parseFloat(d)/100*n:d);b.limit&&/^\d+$/.test(f[g])&&(f[g]=0>=f[g]?0:Math.min(f[g],n));!a&&1<b.axis.length&&(h===f[g]?f={}:u&&(k(b.onAfterFirst),f={}))});k(b.onAfter)}})};p.max=function(a,d){var b="x"===d?"Width":"Height",h="scroll"+b;if(!n(a))return a[h]-$(a)[b.toLowerCase()]();var b="client"+b,k=a.ownerDocument||a.document,l=k.documentElement,k=k.body;return Math.max(l[h],k[h])-Math.min(l[b],k[b])};$.Tween.propHooks.scrollLeft=$.Tween.propHooks.scrollTop={get:function(a){return $(a.elem)[a.prop]()}, set:function(a){var d=this.get(a);if(a.options.interrupt&&a._last&&a._last!==d)return $(a.elem).stop();var b=Math.round(a.now);d!==b&&($(a.elem)[a.prop](b),a._last=this.get(a))}};return p});
@@ -0,0 +1,354 @@
1
+ /*!
2
+ * jQuery.selection - jQuery Plugin
3
+ *
4
+ * Copyright (c) 2010-2014 IWASAKI Koji (@madapaja).
5
+ * http://blog.madapaja.net/
6
+ * Under The MIT License
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining
9
+ * a copy of this software and associated documentation files (the
10
+ * "Software"), to deal in the Software without restriction, including
11
+ * without limitation the rights to use, copy, modify, merge, publish,
12
+ * distribute, sublicense, and/or sell copies of the Software, and to
13
+ * permit persons to whom the Software is furnished to do so, subject to
14
+ * the following conditions:
15
+ *
16
+ * The above copyright notice and this permission notice shall be
17
+ * included in all copies or substantial portions of the Software.
18
+ *
19
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+ (function($, win, doc) {
28
+ /**
29
+ * get caret status of the selection of the element
30
+ *
31
+ * @param {Element} element target DOM element
32
+ * @return {Object} return
33
+ * @return {String} return.text selected text
34
+ * @return {Number} return.start start position of the selection
35
+ * @return {Number} return.end end position of the selection
36
+ */
37
+ var _getCaretInfo = function(element){
38
+ var res = {
39
+ text: '',
40
+ start: 0,
41
+ end: 0
42
+ };
43
+
44
+ if (!element.value) {
45
+ /* no value or empty string */
46
+ return res;
47
+ }
48
+
49
+ try {
50
+ if (win.getSelection) {
51
+ /* except IE */
52
+ res.start = element.selectionStart;
53
+ res.end = element.selectionEnd;
54
+ res.text = element.value.slice(res.start, res.end);
55
+ } else if (doc.selection) {
56
+ /* for IE */
57
+ element.focus();
58
+
59
+ var range = doc.selection.createRange(),
60
+ range2 = doc.body.createTextRange();
61
+
62
+ res.text = range.text;
63
+
64
+ try {
65
+ range2.moveToElementText(element);
66
+ range2.setEndPoint('StartToStart', range);
67
+ } catch (e) {
68
+ range2 = element.createTextRange();
69
+ range2.setEndPoint('StartToStart', range);
70
+ }
71
+
72
+ res.start = element.value.length - range2.text.length;
73
+ res.end = res.start + range.text.length;
74
+ }
75
+ } catch (e) {
76
+ /* give up */
77
+ }
78
+
79
+ return res;
80
+ };
81
+
82
+ /**
83
+ * caret operation for the element
84
+ * @type {Object}
85
+ */
86
+ var _CaretOperation = {
87
+ /**
88
+ * get caret position
89
+ *
90
+ * @param {Element} element target element
91
+ * @return {Object} return
92
+ * @return {Number} return.start start position for the selection
93
+ * @return {Number} return.end end position for the selection
94
+ */
95
+ getPos: function(element) {
96
+ var tmp = _getCaretInfo(element);
97
+ return {start: tmp.start, end: tmp.end};
98
+ },
99
+
100
+ /**
101
+ * set caret position
102
+ *
103
+ * @param {Element} element target element
104
+ * @param {Object} toRange caret position
105
+ * @param {Number} toRange.start start position for the selection
106
+ * @param {Number} toRange.end end position for the selection
107
+ * @param {String} caret caret mode: any of the following: "keep" | "start" | "end"
108
+ */
109
+ setPos: function(element, toRange, caret) {
110
+ caret = this._caretMode(caret);
111
+
112
+ if (caret === 'start') {
113
+ toRange.end = toRange.start;
114
+ } else if (caret === 'end') {
115
+ toRange.start = toRange.end;
116
+ }
117
+
118
+ element.focus();
119
+ try {
120
+ if (element.createTextRange) {
121
+ var range = element.createTextRange();
122
+
123
+ if (win.navigator.userAgent.toLowerCase().indexOf("msie") >= 0) {
124
+ toRange.start = element.value.substr(0, toRange.start).replace(/\r/g, '').length;
125
+ toRange.end = element.value.substr(0, toRange.end).replace(/\r/g, '').length;
126
+ }
127
+
128
+ range.collapse(true);
129
+ range.moveStart('character', toRange.start);
130
+ range.moveEnd('character', toRange.end - toRange.start);
131
+
132
+ range.select();
133
+ } else if (element.setSelectionRange) {
134
+ element.setSelectionRange(toRange.start, toRange.end);
135
+ }
136
+ } catch (e) {
137
+ /* give up */
138
+ }
139
+ },
140
+
141
+ /**
142
+ * get selected text
143
+ *
144
+ * @param {Element} element target element
145
+ * @return {String} return selected text
146
+ */
147
+ getText: function(element) {
148
+ return _getCaretInfo(element).text;
149
+ },
150
+
151
+ /**
152
+ * get caret mode
153
+ *
154
+ * @param {String} caret caret mode
155
+ * @return {String} return any of the following: "keep" | "start" | "end"
156
+ */
157
+ _caretMode: function(caret) {
158
+ caret = caret || "keep";
159
+ if (caret === false) {
160
+ caret = 'end';
161
+ }
162
+
163
+ switch (caret) {
164
+ case 'keep':
165
+ case 'start':
166
+ case 'end':
167
+ break;
168
+
169
+ default:
170
+ caret = 'keep';
171
+ }
172
+
173
+ return caret;
174
+ },
175
+
176
+ /**
177
+ * replace selected text
178
+ *
179
+ * @param {Element} element target element
180
+ * @param {String} text replacement text
181
+ * @param {String} caret caret mode: any of the following: "keep" | "start" | "end"
182
+ */
183
+ replace: function(element, text, caret) {
184
+ var tmp = _getCaretInfo(element),
185
+ orig = element.value,
186
+ pos = $(element).scrollTop(),
187
+ range = {start: tmp.start, end: tmp.start + text.length};
188
+
189
+ element.value = orig.substr(0, tmp.start) + text + orig.substr(tmp.end);
190
+
191
+ $(element).scrollTop(pos);
192
+ this.setPos(element, range, caret);
193
+ },
194
+
195
+ /**
196
+ * insert before the selected text
197
+ *
198
+ * @param {Element} element target element
199
+ * @param {String} text insertion text
200
+ * @param {String} caret caret mode: any of the following: "keep" | "start" | "end"
201
+ */
202
+ insertBefore: function(element, text, caret) {
203
+ var tmp = _getCaretInfo(element),
204
+ orig = element.value,
205
+ pos = $(element).scrollTop(),
206
+ range = {start: tmp.start + text.length, end: tmp.end + text.length};
207
+
208
+ element.value = orig.substr(0, tmp.start) + text + orig.substr(tmp.start);
209
+
210
+ $(element).scrollTop(pos);
211
+ this.setPos(element, range, caret);
212
+ },
213
+
214
+ /**
215
+ * insert after the selected text
216
+ *
217
+ * @param {Element} element target element
218
+ * @param {String} text insertion text
219
+ * @param {String} caret caret mode: any of the following: "keep" | "start" | "end"
220
+ */
221
+ insertAfter: function(element, text, caret) {
222
+ var tmp = _getCaretInfo(element),
223
+ orig = element.value,
224
+ pos = $(element).scrollTop(),
225
+ range = {start: tmp.start, end: tmp.end};
226
+
227
+ element.value = orig.substr(0, tmp.end) + text + orig.substr(tmp.end);
228
+
229
+ $(element).scrollTop(pos);
230
+ this.setPos(element, range, caret);
231
+ }
232
+ };
233
+
234
+ /* add jQuery.selection */
235
+ $.extend({
236
+ /**
237
+ * get selected text on the window
238
+ *
239
+ * @param {String} mode selection mode: any of the following: "text" | "html"
240
+ * @return {String} return
241
+ */
242
+ selection: function(mode) {
243
+ var getText = ((mode || 'text').toLowerCase() === 'text');
244
+
245
+ try {
246
+ if (win.getSelection) {
247
+ if (getText) {
248
+ // get text
249
+ return win.getSelection().toString();
250
+ } else {
251
+ // get html
252
+ var sel = win.getSelection(), range;
253
+
254
+ if (sel.getRangeAt) {
255
+ range = sel.getRangeAt(0);
256
+ } else {
257
+ range = doc.createRange();
258
+ range.setStart(sel.anchorNode, sel.anchorOffset);
259
+ range.setEnd(sel.focusNode, sel.focusOffset);
260
+ }
261
+
262
+ return $('<div></div>').append(range.cloneContents()).html();
263
+ }
264
+ } else if (doc.selection) {
265
+ if (getText) {
266
+ // get text
267
+ return doc.selection.createRange().text;
268
+ } else {
269
+ // get html
270
+ return doc.selection.createRange().htmlText;
271
+ }
272
+ }
273
+ } catch (e) {
274
+ /* give up */
275
+ }
276
+
277
+ return '';
278
+ }
279
+ });
280
+
281
+ /* add selection */
282
+ $.fn.extend({
283
+ selection: function(mode, opts) {
284
+ opts = opts || {};
285
+
286
+ switch (mode) {
287
+ /**
288
+ * selection('getPos')
289
+ * get caret position
290
+ *
291
+ * @return {Object} return
292
+ * @return {Number} return.start start position for the selection
293
+ * @return {Number} return.end end position for the selection
294
+ */
295
+ case 'getPos':
296
+ return _CaretOperation.getPos(this[0]);
297
+
298
+ /**
299
+ * selection('setPos', opts)
300
+ * set caret position
301
+ *
302
+ * @param {Number} opts.start start position for the selection
303
+ * @param {Number} opts.end end position for the selection
304
+ */
305
+ case 'setPos':
306
+ return this.each(function() {
307
+ _CaretOperation.setPos(this, opts);
308
+ });
309
+
310
+ /**
311
+ * selection('replace', opts)
312
+ * replace the selected text
313
+ *
314
+ * @param {String} opts.text replacement text
315
+ * @param {String} opts.caret caret mode: any of the following: "keep" | "start" | "end"
316
+ */
317
+ case 'replace':
318
+ return this.each(function() {
319
+ _CaretOperation.replace(this, opts.text, opts.caret);
320
+ });
321
+
322
+ /**
323
+ * selection('insert', opts)
324
+ * insert before/after the selected text
325
+ *
326
+ * @param {String} opts.text insertion text
327
+ * @param {String} opts.caret caret mode: any of the following: "keep" | "start" | "end"
328
+ * @param {String} opts.mode insertion mode: any of the following: "before" | "after"
329
+ */
330
+ case 'insert':
331
+ return this.each(function() {
332
+ if (opts.mode === 'before') {
333
+ _CaretOperation.insertBefore(this, opts.text, opts.caret);
334
+ } else {
335
+ _CaretOperation.insertAfter(this, opts.text, opts.caret);
336
+ }
337
+ });
338
+
339
+ /**
340
+ * selection('get')
341
+ * get selected text
342
+ *
343
+ * @return {String} return
344
+ */
345
+ case 'get':
346
+ /* falls through */
347
+ default:
348
+ return _CaretOperation.getText(this[0]);
349
+ }
350
+
351
+ return this;
352
+ }
353
+ });
354
+ })(jQuery, window, window.document);
@@ -0,0 +1,118 @@
1
+ ready = ->
2
+ # Quote button
3
+ $('.quote-post').click (event) ->
4
+ quoute_post_id = $(event.target).data('post-id')
5
+
6
+ $.ajax
7
+ url: '/post/' + quoute_post_id
8
+ type: "GET"
9
+ dataType: "json"
10
+ success: (response) ->
11
+ quote = $('#quick_answer_textarea').val()
12
+ quote += '\n[quote author=' + response.author+ ']'
13
+ quote += response.text
14
+ quote += '[/quote]\n\n'
15
+
16
+ $('#quick_answer_textarea').val(quote)
17
+ $('body').scrollTo($('#quick_answer_textarea'))
18
+
19
+
20
+ # BBCode editor
21
+ $('.text-editor-buttons').click (event) ->
22
+ event.preventDefault()
23
+
24
+ apply_to = $('.text-editor-buttons').data('apply-to')
25
+ apply_to = $('#' + apply_to)
26
+
27
+ # Smiles
28
+ if $(event.target).attr('class').search('smile') >= 0
29
+ smile_code = $(event.target).data('code') || $(event.target).find('[data-code]').data('code')
30
+
31
+ if smile_code
32
+ text = apply_to.val()
33
+ apply_to.val(text + smile_code + ' ')
34
+
35
+ return false
36
+
37
+
38
+ # Text formatting
39
+ return false if !$(event.target).is('a') and !$(event.target).is('i')
40
+
41
+ button = if $(event.target).is('a') then $(event.target).find('i') else $(event.target)
42
+ html_class = button.attr('class')
43
+
44
+ action = if html_class then html_class.replace('fa fa-', '') else ''
45
+ text = apply_to.val()
46
+
47
+ switch action
48
+ when 'bold'
49
+ bbcode = '[b] [/b]'
50
+ when 'italic'
51
+ bbcode = '[i] [/i]'
52
+ when 'strikethrough'
53
+ bbcode = '[s] [/s]'
54
+ when 'underline'
55
+ bbcode = '[u] [/u]'
56
+ when 'link', 'video-camera', 'camera-retro'
57
+ $('#add_photo').modal()
58
+ else
59
+ bbcode = ''
60
+ console.log 'Unknown tag'
61
+
62
+ if bbcode
63
+ if (selected_text = apply_to.selection()).length > 0
64
+ open_tag = bbcode.split(' ')[0]
65
+ close_tag = bbcode.split(' ')[1]
66
+ apply_to.selection('replace', { text: open_tag + selected_text + close_tag })
67
+ else
68
+ apply_to.val(text + bbcode + ' ')
69
+
70
+ # Autocomplete
71
+ $('.autocomplete').keyup (elm) ->
72
+ ajax_url = $(@).data('autocomplete-path')
73
+ return unless ajax_url
74
+
75
+ $.ajax
76
+ url: ajax_url
77
+ type: "GET"
78
+ dataType: "json"
79
+ data: str: $(elm.target).val()
80
+ success: (response) ->
81
+ autocomplete_popup(response, elm.target)
82
+
83
+ autocomplete_popup = (autocomplete_list, object) ->
84
+ popup_id = 'autocomplete_popup'
85
+
86
+ # Create or use existing Popup Window
87
+ if $('#' + popup_id).length > 0
88
+ popup_container = $('#' + popup_id)
89
+ else
90
+ popup_container = $("<div id='#{popup_id}'></div>")
91
+ $(object).after(popup_container)
92
+
93
+ $('body').click ->
94
+ popup_container.remove()
95
+
96
+ # Show lists
97
+ html_list = $('<ul/>')
98
+ $.map autocomplete_list, (item) ->
99
+ li = $('<li/>')
100
+ .addClass('ui-menu-item')
101
+ .attr('role', 'menuitem')
102
+ .appendTo(html_list)
103
+
104
+ a = $('<a/>')
105
+ .addClass('ui-all')
106
+ .text(item)
107
+ .appendTo(li)
108
+
109
+ li.click ->
110
+ $(object).val(item)
111
+
112
+ # Destroy popup after select tag
113
+ popup_container.remove()
114
+
115
+ popup_container.html(html_list)
116
+
117
+ $(document).ready(ready)
118
+ $(document).on('page:load', ready)
@@ -0,0 +1,20 @@
1
+ ready = ->
2
+ $('#post_preview').click (event) ->
3
+ event.preventDefault()
4
+
5
+ elm_id = $(event.target).data('elm-preview')
6
+ elm = $('#' + elm_id)
7
+
8
+ return unless elm
9
+
10
+ data = elm.val()
11
+
12
+ $.ajax
13
+ url: '/post/preview'
14
+ type: 'POST'
15
+ dataType: 'script'
16
+ data:
17
+ text: data
18
+
19
+ $(document).ready(ready)
20
+ $(document).on('page:load', ready)
File without changes
File without changes
File without changes
@@ -0,0 +1,3 @@
1
+ #admin-content {
2
+ margin-top: 52px;
3
+ }
@@ -0,0 +1,7 @@
1
+ .category_box {
2
+ border: 1px solid #DEDEDE;
3
+
4
+ .category_name {
5
+ background-color: darkgrey;
6
+ }
7
+ }
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */