tawork 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (239) hide show
  1. checksums.yaml +7 -0
  2. data/.DS_Store +0 -0
  3. data/.gitignore +16 -0
  4. data/Gemfile +91 -0
  5. data/Gemfile.lock +295 -0
  6. data/MIT-LICENSE +20 -0
  7. data/Procfile +2 -0
  8. data/README.md +1 -0
  9. data/Rakefile +6 -0
  10. data/app/assets/images/.keep +0 -0
  11. data/app/assets/javascripts/application.js +31 -0
  12. data/app/assets/javascripts/backbone/models/.gitkeep +0 -0
  13. data/app/assets/javascripts/backbone/routers/.gitkeep +0 -0
  14. data/app/assets/javascripts/backbone/tawork.js.coffee +11 -0
  15. data/app/assets/javascripts/backbone/templates/.gitkeep +0 -0
  16. data/app/assets/javascripts/backbone/views/.gitkeep +0 -0
  17. data/app/assets/javascripts/backbone/views/page.js.coffee +75 -0
  18. data/app/assets/javascripts/backbone/views/ticket.js.coffee +110 -0
  19. data/app/assets/javascripts/backbone/views/tree_node_page.js.coffee +16 -0
  20. data/app/assets/javascripts/backbone/views/tree_node_ticket.js.coffee +14 -0
  21. data/app/assets/javascripts/wiki/pages.js.coffee +3 -0
  22. data/app/assets/stylesheets/application.css +22 -0
  23. data/app/assets/stylesheets/bootstrap_and_overrides.sass +208 -0
  24. data/app/assets/stylesheets/diff.css +14 -0
  25. data/app/assets/stylesheets/wiki/pages.css.scss +3 -0
  26. data/app/controllers/application_controller.rb +15 -0
  27. data/app/controllers/assignments_controller.rb +30 -0
  28. data/app/controllers/attachments_controller.rb +10 -0
  29. data/app/controllers/comments_controller.rb +24 -0
  30. data/app/controllers/concerns/.keep +0 -0
  31. data/app/controllers/home_controller.rb +7 -0
  32. data/app/controllers/projects_controller.rb +31 -0
  33. data/app/controllers/search_controller.rb +49 -0
  34. data/app/controllers/sink_controller.rb +10 -0
  35. data/app/controllers/tickets_controller.rb +147 -0
  36. data/app/controllers/users/omniauth_callbacks_controller.rb +23 -0
  37. data/app/controllers/wiki/pages_controller.rb +115 -0
  38. data/app/controllers/wiki/spaces_controller.rb +37 -0
  39. data/app/helpers/application_helper.rb +20 -0
  40. data/app/helpers/wiki/pages_helper.rb +2 -0
  41. data/app/inputs/fake_input.rb +6 -0
  42. data/app/mailers/.keep +0 -0
  43. data/app/models/.keep +0 -0
  44. data/app/models/assignment.rb +5 -0
  45. data/app/models/attachment.rb +54 -0
  46. data/app/models/bug.rb +2 -0
  47. data/app/models/comment.rb +6 -0
  48. data/app/models/concerns/.keep +0 -0
  49. data/app/models/page.rb +68 -0
  50. data/app/models/project.rb +2 -0
  51. data/app/models/space.rb +2 -0
  52. data/app/models/story.rb +29 -0
  53. data/app/models/story_detail.rb +3 -0
  54. data/app/models/task.rb +2 -0
  55. data/app/models/ticket.rb +127 -0
  56. data/app/models/user.rb +36 -0
  57. data/app/models/user_verifier.rb +2 -0
  58. data/app/views/comments/_comment.html.haml +6 -0
  59. data/app/views/comments/_form.html.haml +4 -0
  60. data/app/views/comments/create.js.coffee +7 -0
  61. data/app/views/devise/confirmations/new.html.erb +12 -0
  62. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  63. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  64. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  65. data/app/views/devise/passwords/edit.html.erb +16 -0
  66. data/app/views/devise/passwords/new.html.erb +12 -0
  67. data/app/views/devise/registrations/edit.html.erb +29 -0
  68. data/app/views/devise/registrations/new.html.erb +18 -0
  69. data/app/views/devise/sessions/new.html.erb +17 -0
  70. data/app/views/devise/shared/_links.erb +25 -0
  71. data/app/views/devise/unlocks/new.html.erb +12 -0
  72. data/app/views/home/index.html.haml +4 -0
  73. data/app/views/layouts/_activity_wrapper.html.haml +17 -0
  74. data/app/views/layouts/_nav_header.html.haml +26 -0
  75. data/app/views/layouts/_spaces.html.haml +34 -0
  76. data/app/views/layouts/application.html.haml +39 -0
  77. data/app/views/layouts/minimal.html.haml +22 -0
  78. data/app/views/projects/index.html.haml +16 -0
  79. data/app/views/projects/new.html.haml +6 -0
  80. data/app/views/public_activity/ticket/_assignment.html.haml +14 -0
  81. data/app/views/public_activity/ticket/_create_comment.html.haml +10 -0
  82. data/app/views/public_activity/ticket/_created.html.haml +3 -0
  83. data/app/views/public_activity/ticket/_reorder.html.haml +2 -0
  84. data/app/views/public_activity/ticket/_state_change.html.haml +2 -0
  85. data/app/views/public_activity/ticket/_update_details.html.haml +13 -0
  86. data/app/views/tickets/_activity.html.haml +3 -0
  87. data/app/views/tickets/_breadcrumb.html.haml +7 -0
  88. data/app/views/tickets/_bug_form.html.haml +1 -0
  89. data/app/views/tickets/_events_dropdown.html.haml +4 -0
  90. data/app/views/tickets/_form.html.haml +28 -0
  91. data/app/views/tickets/_project_form.html.haml +1 -0
  92. data/app/views/tickets/_story_form.html.haml +15 -0
  93. data/app/views/tickets/_task_form.html.haml +8 -0
  94. data/app/views/tickets/_tickets_listing.html.haml +5 -0
  95. data/app/views/tickets/_title_and_description.html.haml +8 -0
  96. data/app/views/tickets/_tree_node.html.haml +28 -0
  97. data/app/views/tickets/assignment.js.coffee +3 -0
  98. data/app/views/tickets/create.js.coffee +7 -0
  99. data/app/views/tickets/new.html.haml +1 -0
  100. data/app/views/tickets/show.html.haml +64 -0
  101. data/app/views/tickets/trigger_event.js.coffee +12 -0
  102. data/app/views/tickets/update.js.coffee +12 -0
  103. data/app/views/wiki/pages/_attachment.html.haml +5 -0
  104. data/app/views/wiki/pages/_attachments.html.haml +22 -0
  105. data/app/views/wiki/pages/_breadcrumb.html.haml +9 -0
  106. data/app/views/wiki/pages/_child_menu.html.haml +9 -0
  107. data/app/views/wiki/pages/_display.html.haml +138 -0
  108. data/app/views/wiki/pages/_page_header.html.haml +13 -0
  109. data/app/views/wiki/pages/_subpages_dropdown.html.haml +6 -0
  110. data/app/views/wiki/pages/_subtree.html.haml +7 -0
  111. data/app/views/wiki/pages/_tree_node.html.haml +21 -0
  112. data/app/views/wiki/pages/attach.js.coffee +2 -0
  113. data/app/views/wiki/pages/combined.html.haml +8 -0
  114. data/app/views/wiki/pages/create.js.coffee +5 -0
  115. data/app/views/wiki/pages/edit.html.haml +2 -0
  116. data/app/views/wiki/pages/history.html.haml +13 -0
  117. data/app/views/wiki/pages/index.html.haml +2 -0
  118. data/app/views/wiki/pages/new.html.haml +13 -0
  119. data/app/views/wiki/pages/show.html.haml +14 -0
  120. data/app/views/wiki/pages/update.html.haml +2 -0
  121. data/app/views/wiki/spaces/_page_list_item.html.haml +11 -0
  122. data/app/views/wiki/spaces/_space_list.html.haml +4 -0
  123. data/app/views/wiki/spaces/new.html.haml +5 -0
  124. data/app/views/wiki/spaces/space_list.html.haml +1 -0
  125. data/bin/bundle +3 -0
  126. data/bin/rails +4 -0
  127. data/bin/rake +4 -0
  128. data/config/application.rb +30 -0
  129. data/config/boot.rb +4 -0
  130. data/config/database.yml +39 -0
  131. data/config/environment.rb +5 -0
  132. data/config/environments/development.rb +35 -0
  133. data/config/environments/production.rb +80 -0
  134. data/config/environments/test.rb +36 -0
  135. data/config/initializers/backtrace_silencers.rb +7 -0
  136. data/config/initializers/config.rb +4 -0
  137. data/config/initializers/devise.rb +257 -0
  138. data/config/initializers/elasticsearch.rb +9 -0
  139. data/config/initializers/filter_parameter_logging.rb +4 -0
  140. data/config/initializers/gollum.rb +31 -0
  141. data/config/initializers/haml_gfm.rb +66 -0
  142. data/config/initializers/inflections.rb +16 -0
  143. data/config/initializers/mime_types.rb +5 -0
  144. data/config/initializers/secret_token.rb +12 -0
  145. data/config/initializers/session_store.rb +3 -0
  146. data/config/initializers/simple_form.rb +145 -0
  147. data/config/initializers/simple_form_bootstrap.rb +73 -0
  148. data/config/initializers/wrap_parameters.rb +14 -0
  149. data/config/locales/devise.en.yml +59 -0
  150. data/config/locales/en.yml +23 -0
  151. data/config/locales/simple_form.en.yml +26 -0
  152. data/config/routes.rb +101 -0
  153. data/config/tinymce.yml +10 -0
  154. data/config.ru +4 -0
  155. data/db/migrate/20131209041251_create_tickets.rb +13 -0
  156. data/db/migrate/20131210041050_devise_create_users.rb +42 -0
  157. data/db/migrate/20131210043014_add_username_to_users.rb +5 -0
  158. data/db/migrate/20131210045348_add_creator_to_ticket.rb +5 -0
  159. data/db/migrate/20131211034104_create_comments.rb +11 -0
  160. data/db/migrate/20131212073014_create_assignments.rb +12 -0
  161. data/db/migrate/20131215220825_add_position_to_ticket.rb +5 -0
  162. data/db/migrate/20131216044331_create_story_details.rb +12 -0
  163. data/db/migrate/20131218060557_create_activities.rb +23 -0
  164. data/db/migrate/20140109235844_create_pages.rb +14 -0
  165. data/db/migrate/20140112004346_create_attachments.rb +13 -0
  166. data/db/migrate/20140120030547_add_name_to_users.rb +5 -0
  167. data/db/schema.rb +125 -0
  168. data/db/seeds.rb +7 -0
  169. data/init.rb +1 -0
  170. data/lib/assets/.keep +0 -0
  171. data/lib/tasks/.keep +0 -0
  172. data/lib/tawork/engine.rb +13 -0
  173. data/lib/tawork/version.rb +3 -0
  174. data/lib/tawork.rb +4 -0
  175. data/lib/templates/haml/scaffold/_form.html.haml +10 -0
  176. data/lib/ticket_assignment.rb +25 -0
  177. data/log/.keep +0 -0
  178. data/public/401.html +57 -0
  179. data/public/404.html +58 -0
  180. data/public/422.html +58 -0
  181. data/public/500.html +57 -0
  182. data/public/favicon.ico +0 -0
  183. data/public/robots.txt +5 -0
  184. data/tags +279 -0
  185. data/tawork.gemspec +24 -0
  186. data/vendor/.DS_Store +0 -0
  187. data/vendor/assets/.DS_Store +0 -0
  188. data/vendor/assets/javascripts/.keep +0 -0
  189. data/vendor/assets/javascripts/bootstrap-tagsinput.js +503 -0
  190. data/vendor/assets/javascripts/bootstrap-tree.js +15 -0
  191. data/vendor/assets/javascripts/bootstrap-typeahead.js +335 -0
  192. data/vendor/assets/javascripts/hallo.js +2949 -0
  193. data/vendor/assets/javascripts/highlight.pack.js +1 -0
  194. data/vendor/assets/javascripts/jquery.autosize.js +250 -0
  195. data/vendor/assets/javascripts/jquery.mjs.nestedSortable.js +613 -0
  196. data/vendor/assets/javascripts/rangy-core.js +94 -0
  197. data/vendor/assets/javascripts/tinymce/mention/plugin.js +358 -0
  198. data/vendor/assets/stylesheets/.keep +0 -0
  199. data/vendor/assets/stylesheets/bootflat-extensions.css +356 -0
  200. data/vendor/assets/stylesheets/bootflat-square.css +69 -0
  201. data/vendor/assets/stylesheets/bootflat.css +1556 -0
  202. data/vendor/assets/stylesheets/bootstrap-tagsinput.css +45 -0
  203. data/vendor/assets/stylesheets/bootstrap-tree.sass +82 -0
  204. data/vendor/assets/stylesheets/highlight/arta.css +160 -0
  205. data/vendor/assets/stylesheets/highlight/ascetic.css +50 -0
  206. data/vendor/assets/stylesheets/highlight/brown_paper.css +105 -0
  207. data/vendor/assets/stylesheets/highlight/brown_papersq.png +0 -0
  208. data/vendor/assets/stylesheets/highlight/dark.css +105 -0
  209. data/vendor/assets/stylesheets/highlight/default.css +153 -0
  210. data/vendor/assets/stylesheets/highlight/docco.css +132 -0
  211. data/vendor/assets/stylesheets/highlight/far.css +113 -0
  212. data/vendor/assets/stylesheets/highlight/foundation.css +133 -0
  213. data/vendor/assets/stylesheets/highlight/github.css +130 -0
  214. data/vendor/assets/stylesheets/highlight/googlecode.css +146 -0
  215. data/vendor/assets/stylesheets/highlight/idea.css +122 -0
  216. data/vendor/assets/stylesheets/highlight/ir_black.css +105 -0
  217. data/vendor/assets/stylesheets/highlight/magula.css +123 -0
  218. data/vendor/assets/stylesheets/highlight/mono-blue.css +62 -0
  219. data/vendor/assets/stylesheets/highlight/monokai.css +127 -0
  220. data/vendor/assets/stylesheets/highlight/monokai_sublime.css +102 -0
  221. data/vendor/assets/stylesheets/highlight/obsidian.css +154 -0
  222. data/vendor/assets/stylesheets/highlight/pojoaque.css +105 -0
  223. data/vendor/assets/stylesheets/highlight/pojoaque.jpg +0 -0
  224. data/vendor/assets/stylesheets/highlight/railscasts.css +182 -0
  225. data/vendor/assets/stylesheets/highlight/rainbow.css +115 -0
  226. data/vendor/assets/stylesheets/highlight/school_book.css +113 -0
  227. data/vendor/assets/stylesheets/highlight/school_book.png +0 -0
  228. data/vendor/assets/stylesheets/highlight/solarized_dark.css +92 -0
  229. data/vendor/assets/stylesheets/highlight/solarized_light.css +92 -0
  230. data/vendor/assets/stylesheets/highlight/sunburst.css +160 -0
  231. data/vendor/assets/stylesheets/highlight/tomorrow-night-blue.css +52 -0
  232. data/vendor/assets/stylesheets/highlight/tomorrow-night-bright.css +51 -0
  233. data/vendor/assets/stylesheets/highlight/tomorrow-night-eighties.css +51 -0
  234. data/vendor/assets/stylesheets/highlight/tomorrow-night.css +52 -0
  235. data/vendor/assets/stylesheets/highlight/tomorrow.css +49 -0
  236. data/vendor/assets/stylesheets/highlight/vs.css +89 -0
  237. data/vendor/assets/stylesheets/highlight/xcode.css +157 -0
  238. data/vendor/assets/stylesheets/highlight/zenburn.css +117 -0
  239. metadata +299 -0
data/tawork.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ # Maintain your gem's version:
4
+ require "tawork/version"
5
+
6
+ # Describe your gem and declare its dependencies:
7
+ Gem::Specification.new do |s|
8
+ s.name = "tawork"
9
+ s.version = Tawork::VERSION
10
+ s.authors = ["Adnan Ali"]
11
+ s.email = ["adnan.ali@gmail.com"]
12
+ s.homepage = ""
13
+ s.summary = "Wiki and Tickets"
14
+ s.description = "Wiki and Tickets"
15
+ s.license = "MIT"
16
+
17
+ s.files = `git ls-files`.split($/)
18
+ s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
19
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
20
+
21
+ s.add_dependency "rails", "~> 4.1.0.beta1"
22
+
23
+ s.require_paths = ['lib']
24
+ end
data/vendor/.DS_Store ADDED
Binary file
Binary file
File without changes
@@ -0,0 +1,503 @@
1
+ (function ($) {
2
+ "use strict";
3
+
4
+ var defaultOptions = {
5
+ tagClass: function(item) {
6
+ return 'label label-info';
7
+ },
8
+ itemValue: function(item) {
9
+ return item ? item.toString() : item;
10
+ },
11
+ itemText: function(item) {
12
+ return this.itemValue(item);
13
+ },
14
+ freeInput: true,
15
+ maxTags: undefined,
16
+ confirmKeys: [13],
17
+ onTagExists: function(item, $tag) {
18
+ $tag.hide().fadeIn();
19
+ }
20
+ };
21
+
22
+ /**
23
+ * Constructor function
24
+ */
25
+ function TagsInput(element, options) {
26
+ this.itemsArray = [];
27
+
28
+ this.$element = $(element);
29
+ this.$element.hide();
30
+
31
+ this.isSelect = (element.tagName === 'SELECT');
32
+ this.multiple = (this.isSelect && element.hasAttribute('multiple'));
33
+ this.objectItems = options && options.itemValue;
34
+ this.placeholderText = element.hasAttribute('placeholder') ? this.$element.attr('placeholder') : '';
35
+ this.inputSize = Math.max(1, this.placeholderText.length);
36
+
37
+ this.$container = $('<div class="bootstrap-tagsinput"></div>');
38
+ this.$input = $('<input size="' + this.inputSize + '" type="text" placeholder="' + this.placeholderText + '"/>').appendTo(this.$container);
39
+
40
+ this.$element.after(this.$container);
41
+
42
+ this.build(options);
43
+ }
44
+
45
+ TagsInput.prototype = {
46
+ constructor: TagsInput,
47
+
48
+ /**
49
+ * Adds the given item as a new tag. Pass true to dontPushVal to prevent
50
+ * updating the elements val()
51
+ */
52
+ add: function(item, dontPushVal) {
53
+ var self = this;
54
+
55
+ if (self.options.maxTags && self.itemsArray.length >= self.options.maxTags)
56
+ return;
57
+
58
+ // Ignore falsey values, except false
59
+ if (item !== false && !item)
60
+ return;
61
+
62
+ // Throw an error when trying to add an object while the itemValue option was not set
63
+ if (typeof item === "object" && !self.objectItems)
64
+ throw("Can't add objects when itemValue option is not set");
65
+
66
+ // Ignore strings only containg whitespace
67
+ if (item.toString().match(/^\s*$/))
68
+ return;
69
+
70
+ // If SELECT but not multiple, remove current tag
71
+ if (self.isSelect && !self.multiple && self.itemsArray.length > 0)
72
+ self.remove(self.itemsArray[0]);
73
+
74
+ if (typeof item === "string" && this.$element[0].tagName === 'INPUT') {
75
+ var items = item.split(',');
76
+ if (items.length > 1) {
77
+ for (var i = 0; i < items.length; i++) {
78
+ this.add(items[i], true);
79
+ }
80
+
81
+ if (!dontPushVal)
82
+ self.pushVal();
83
+ return;
84
+ }
85
+ }
86
+
87
+ var itemValue = self.options.itemValue(item),
88
+ itemText = self.options.itemText(item),
89
+ tagClass = self.options.tagClass(item);
90
+
91
+ // Ignore items allready added
92
+ var existing = $.grep(self.itemsArray, function(item) { return self.options.itemValue(item) === itemValue; } )[0];
93
+ if (existing) {
94
+ // Invoke onTagExists
95
+ if (self.options.onTagExists) {
96
+ var $existingTag = $(".tag", self.$container).filter(function() { return $(this).data("item") === existing; });
97
+ self.options.onTagExists(item, $existingTag);
98
+ }
99
+ return;
100
+ }
101
+
102
+ // register item in internal array and map
103
+ self.itemsArray.push(item);
104
+
105
+ // add a tag element
106
+ var $tag = $('<span class="tag ' + htmlEncode(tagClass) + '">' + htmlEncode(itemText) + '<span data-role="remove"></span></span>');
107
+ $tag.data('item', item);
108
+ self.findInputWrapper().before($tag);
109
+ $tag.after(' ');
110
+
111
+ // add <option /> if item represents a value not present in one of the <select />'s options
112
+ if (self.isSelect && !$('option[value="' + escape(itemValue) + '"]',self.$element)[0]) {
113
+ var $option = $('<option selected>' + htmlEncode(itemText) + '</option>');
114
+ $option.data('item', item);
115
+ $option.attr('value', itemValue);
116
+ self.$element.append($option);
117
+ }
118
+
119
+ if (!dontPushVal)
120
+ self.pushVal();
121
+
122
+ // Add class when reached maxTags
123
+ if (self.options.maxTags === self.itemsArray.length)
124
+ self.$container.addClass('bootstrap-tagsinput-max');
125
+
126
+ self.$element.trigger($.Event('itemAdded', { item: item }));
127
+ },
128
+
129
+ /**
130
+ * Removes the given item. Pass true to dontPushVal to prevent updating the
131
+ * elements val()
132
+ */
133
+ remove: function(item, dontPushVal) {
134
+ var self = this;
135
+
136
+ if (self.objectItems) {
137
+ if (typeof item === "object")
138
+ item = $.grep(self.itemsArray, function(other) { return self.options.itemValue(other) == self.options.itemValue(item); } )[0];
139
+ else
140
+ item = $.grep(self.itemsArray, function(other) { return self.options.itemValue(other) == item; } )[0];
141
+ }
142
+
143
+ if (item) {
144
+ $('.tag', self.$container).filter(function() { return $(this).data('item') === item; }).remove();
145
+ $('option', self.$element).filter(function() { return $(this).data('item') === item; }).remove();
146
+ self.itemsArray.splice($.inArray(item, self.itemsArray), 1);
147
+ }
148
+
149
+ if (!dontPushVal)
150
+ self.pushVal();
151
+
152
+ // Remove class when reached maxTags
153
+ if (self.options.maxTags > self.itemsArray.length)
154
+ self.$container.removeClass('bootstrap-tagsinput-max');
155
+
156
+ self.$element.trigger($.Event('itemRemoved', { item: item }));
157
+ },
158
+
159
+ /**
160
+ * Removes all items
161
+ */
162
+ removeAll: function() {
163
+ var self = this;
164
+
165
+ $('.tag', self.$container).remove();
166
+ $('option', self.$element).remove();
167
+
168
+ while(self.itemsArray.length > 0)
169
+ self.itemsArray.pop();
170
+
171
+ self.pushVal();
172
+
173
+ if (self.options.maxTags && !this.isEnabled())
174
+ this.enable();
175
+ },
176
+
177
+ /**
178
+ * Refreshes the tags so they match the text/value of their corresponding
179
+ * item.
180
+ */
181
+ refresh: function() {
182
+ var self = this;
183
+ $('.tag', self.$container).each(function() {
184
+ var $tag = $(this),
185
+ item = $tag.data('item'),
186
+ itemValue = self.options.itemValue(item),
187
+ itemText = self.options.itemText(item),
188
+ tagClass = self.options.tagClass(item);
189
+
190
+ // Update tag's class and inner text
191
+ $tag.attr('class', null);
192
+ $tag.addClass('tag ' + htmlEncode(tagClass));
193
+ $tag.contents().filter(function() {
194
+ return this.nodeType == 3;
195
+ })[0].nodeValue = htmlEncode(itemText);
196
+
197
+ if (self.isSelect) {
198
+ var option = $('option', self.$element).filter(function() { return $(this).data('item') === item; });
199
+ option.attr('value', itemValue);
200
+ }
201
+ });
202
+ },
203
+
204
+ /**
205
+ * Returns the items added as tags
206
+ */
207
+ items: function() {
208
+ return this.itemsArray;
209
+ },
210
+
211
+ /**
212
+ * Assembly value by retrieving the value of each item, and set it on the
213
+ * element.
214
+ */
215
+ pushVal: function() {
216
+ var self = this,
217
+ val = $.map(self.items(), function(item) {
218
+ return self.options.itemValue(item).toString();
219
+ });
220
+
221
+ self.$element.val(val, true).trigger('change');
222
+ },
223
+
224
+ /**
225
+ * Initializes the tags input behaviour on the element
226
+ */
227
+ build: function(options) {
228
+ var self = this;
229
+
230
+ self.options = $.extend({}, defaultOptions, options);
231
+ var typeahead = self.options.typeahead || {};
232
+
233
+ // When itemValue is set, freeInput should always be false
234
+ if (self.objectItems)
235
+ self.options.freeInput = false;
236
+
237
+ makeOptionItemFunction(self.options, 'itemValue');
238
+ makeOptionItemFunction(self.options, 'itemText');
239
+ makeOptionItemFunction(self.options, 'tagClass');
240
+
241
+ // for backwards compatibility, self.options.source is deprecated
242
+ if (self.options.source)
243
+ typeahead.source = self.options.source;
244
+
245
+ if (typeahead.source && $.fn.typeahead) {
246
+ makeOptionFunction(typeahead, 'source');
247
+
248
+ self.$input.typeahead({
249
+ source: function (query, process) {
250
+ function processItems(items) {
251
+ var texts = [];
252
+
253
+ for (var i = 0; i < items.length; i++) {
254
+ var text = self.options.itemText(items[i]);
255
+ map[text] = items[i];
256
+ texts.push(text);
257
+ }
258
+ process(texts);
259
+ }
260
+
261
+ this.map = {};
262
+ var map = this.map,
263
+ data = typeahead.source(query);
264
+
265
+ if ($.isFunction(data.success)) {
266
+ // support for Angular promises
267
+ data.success(processItems);
268
+ } else {
269
+ // support for functions and jquery promises
270
+ $.when(data)
271
+ .then(processItems);
272
+ }
273
+ },
274
+ updater: function (text) {
275
+ self.add(this.map[text]);
276
+ },
277
+ matcher: function (text) {
278
+ return (text.toLowerCase().indexOf(this.query.trim().toLowerCase()) !== -1);
279
+ },
280
+ sorter: function (texts) {
281
+ return texts.sort();
282
+ },
283
+ highlighter: function (text) {
284
+ var regex = new RegExp( '(' + this.query + ')', 'gi' );
285
+ return text.replace( regex, "<strong>$1</strong>" );
286
+ }
287
+ });
288
+ }
289
+
290
+ self.$container.on('click', $.proxy(function(event) {
291
+ self.$input.focus();
292
+ }, self));
293
+
294
+ self.$container.on('keydown', 'input', $.proxy(function(event) {
295
+ var $input = $(event.target),
296
+ $inputWrapper = self.findInputWrapper();
297
+
298
+ switch (event.which) {
299
+ // BACKSPACE
300
+ case 8:
301
+ if (doGetCaretPosition($input[0]) === 0) {
302
+ var prev = $inputWrapper.prev();
303
+ if (prev) {
304
+ self.remove(prev.data('item'));
305
+ }
306
+ }
307
+ break;
308
+
309
+ // DELETE
310
+ case 46:
311
+ if (doGetCaretPosition($input[0]) === 0) {
312
+ var next = $inputWrapper.next();
313
+ if (next) {
314
+ self.remove(next.data('item'));
315
+ }
316
+ }
317
+ break;
318
+
319
+ // LEFT ARROW
320
+ case 37:
321
+ // Try to move the input before the previous tag
322
+ var $prevTag = $inputWrapper.prev();
323
+ if ($input.val().length === 0 && $prevTag[0]) {
324
+ $prevTag.before($inputWrapper);
325
+ $input.focus();
326
+ }
327
+ break;
328
+ // RIGHT ARROW
329
+ case 39:
330
+ // Try to move the input after the next tag
331
+ var $nextTag = $inputWrapper.next();
332
+ if ($input.val().length === 0 && $nextTag[0]) {
333
+ $nextTag.after($inputWrapper);
334
+ $input.focus();
335
+ }
336
+ break;
337
+ default:
338
+ // When key corresponds one of the confirmKeys, add current input
339
+ // as a new tag
340
+ if (self.options.freeInput && $.inArray(event.which, self.options.confirmKeys) >= 0) {
341
+ self.add($input.val());
342
+ $input.val('');
343
+ event.preventDefault();
344
+ }
345
+ }
346
+
347
+ // Reset internal input's size
348
+ $input.attr('size', Math.max(this.inputSize, $input.val().length));
349
+ }, self));
350
+
351
+ // Remove icon clicked
352
+ self.$container.on('click', '[data-role=remove]', $.proxy(function(event) {
353
+ self.remove($(event.target).closest('.tag').data('item'));
354
+ }, self));
355
+
356
+ // Only add existing value as tags when using strings as tags
357
+ if (self.options.itemValue === defaultOptions.itemValue) {
358
+ if (self.$element[0].tagName === 'INPUT') {
359
+ self.add(self.$element.val());
360
+ } else {
361
+ $('option', self.$element).each(function() {
362
+ self.add($(this).attr('value'), true);
363
+ });
364
+ }
365
+ }
366
+ },
367
+
368
+ /**
369
+ * Removes all tagsinput behaviour and unregsiter all event handlers
370
+ */
371
+ destroy: function() {
372
+ var self = this;
373
+
374
+ // Unbind events
375
+ self.$container.off('keypress', 'input');
376
+ self.$container.off('click', '[role=remove]');
377
+
378
+ self.$container.remove();
379
+ self.$element.removeData('tagsinput');
380
+ self.$element.show();
381
+ },
382
+
383
+ /**
384
+ * Sets focus on the tagsinput
385
+ */
386
+ focus: function() {
387
+ this.$input.focus();
388
+ },
389
+
390
+ /**
391
+ * Returns the internal input element
392
+ */
393
+ input: function() {
394
+ return this.$input;
395
+ },
396
+
397
+ /**
398
+ * Returns the element which is wrapped around the internal input. This
399
+ * is normally the $container, but typeahead.js moves the $input element.
400
+ */
401
+ findInputWrapper: function() {
402
+ var elt = this.$input[0],
403
+ container = this.$container[0];
404
+ while(elt && elt.parentNode !== container)
405
+ elt = elt.parentNode;
406
+
407
+ return $(elt);
408
+ }
409
+ };
410
+
411
+ /**
412
+ * Register JQuery plugin
413
+ */
414
+ $.fn.tagsinput = function(arg1, arg2) {
415
+ var results = [];
416
+
417
+ this.each(function() {
418
+ var tagsinput = $(this).data('tagsinput');
419
+
420
+ // Initialize a new tags input
421
+ if (!tagsinput) {
422
+ tagsinput = new TagsInput(this, arg1);
423
+ $(this).data('tagsinput', tagsinput);
424
+ results.push(tagsinput);
425
+
426
+ if (this.tagName === 'SELECT') {
427
+ $('option', $(this)).attr('selected', 'selected');
428
+ }
429
+
430
+ // Init tags from $(this).val()
431
+ $(this).val($(this).val());
432
+ } else {
433
+ // Invoke function on existing tags input
434
+ var retVal = tagsinput[arg1](arg2);
435
+ if (retVal !== undefined)
436
+ results.push(retVal);
437
+ }
438
+ });
439
+
440
+ if ( typeof arg1 == 'string') {
441
+ // Return the results from the invoked function calls
442
+ return results.length > 1 ? results : results[0];
443
+ } else {
444
+ return results;
445
+ }
446
+ };
447
+
448
+ $.fn.tagsinput.Constructor = TagsInput;
449
+
450
+ /**
451
+ * Most options support both a string or number as well as a function as
452
+ * option value. This function makes sure that the option with the given
453
+ * key in the given options is wrapped in a function
454
+ */
455
+ function makeOptionItemFunction(options, key) {
456
+ if (typeof options[key] !== 'function') {
457
+ var propertyName = options[key];
458
+ options[key] = function(item) { return item[propertyName]; };
459
+ }
460
+ }
461
+ function makeOptionFunction(options, key) {
462
+ if (typeof options[key] !== 'function') {
463
+ var value = options[key];
464
+ options[key] = function() { return value; };
465
+ }
466
+ }
467
+ /**
468
+ * HtmlEncodes the given value
469
+ */
470
+ var htmlEncodeContainer = $('<div />');
471
+ function htmlEncode(value) {
472
+ if (value) {
473
+ return htmlEncodeContainer.text(value).html();
474
+ } else {
475
+ return '';
476
+ }
477
+ }
478
+
479
+ /**
480
+ * Returns the position of the caret in the given input field
481
+ * http://flightschool.acylt.com/devnotes/caret-position-woes/
482
+ */
483
+ function doGetCaretPosition(oField) {
484
+ var iCaretPos = 0;
485
+ if (document.selection) {
486
+ oField.focus ();
487
+ var oSel = document.selection.createRange();
488
+ oSel.moveStart ('character', -oField.value.length);
489
+ iCaretPos = oSel.text.length;
490
+ } else if (oField.selectionStart || oField.selectionStart == '0') {
491
+ iCaretPos = oField.selectionStart;
492
+ }
493
+ return (iCaretPos);
494
+ }
495
+
496
+ /**
497
+ * Initialize tagsinput behaviour on inputs and selects which have
498
+ * data-role=tagsinput
499
+ */
500
+ $(function() {
501
+ $("input[data-role=tagsinput], select[multiple][data-role=tagsinput]").tagsinput();
502
+ });
503
+ })(window.jQuery);
@@ -0,0 +1,15 @@
1
+ $(document).ready(function() {
2
+ $('.tree > ul').attr('role', 'tree').find('ul').attr('role', 'group');
3
+ $('.tree').find('li:has(ul)').addClass('parent_li').attr('role', 'treeitem').find(' > .label-node-holder > span.node').attr('title', 'Collapse this branch').on('click', function (e) {
4
+ var children = $(this).parent().parent('li.parent_li').find(' > ul > li');
5
+ if (children.is(':visible')) {
6
+ children.slideUp();
7
+ $(this).attr('title', 'Expand this branch').find(' > i').addClass('fa-plus-circle').removeClass('fa-minus-circle');
8
+ }
9
+ else {
10
+ children.slideDown();
11
+ $(this).attr('title', 'Collapse this branch').find(' > i').addClass('fa-minus-circle').removeClass('fa-plus-circle');
12
+ }
13
+ e.stopPropagation();
14
+ });
15
+ });