iqvoc 3.5.7 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (174) hide show
  1. data/CHANGELOG.md +7 -0
  2. data/Gemfile +4 -1
  3. data/Gemfile.lock +13 -22
  4. data/app/assets/images/iqvoc_logo.png +0 -0
  5. data/app/assets/images/spinner_16x16.gif +0 -0
  6. data/app/assets/images/spinner_24x24.gif +0 -0
  7. data/app/assets/javascripts/framework.js +1 -0
  8. data/app/assets/javascripts/iqvoc/entityselect.js.erb +102 -102
  9. data/app/assets/javascripts/iqvoc/iqvoc.js +182 -238
  10. data/app/assets/javascripts/iqvoc/langselect.js +1 -1
  11. data/app/assets/javascripts/iqvoc/visualization.js +247 -247
  12. data/app/assets/stylesheets/framework.css +2 -0
  13. data/app/assets/stylesheets/iqvoc/bootstrap_extensions.css.scss +77 -0
  14. data/app/assets/stylesheets/iqvoc/components.css.scss +76 -0
  15. data/app/assets/stylesheets/iqvoc/entity_select.css.scss +56 -0
  16. data/app/assets/stylesheets/iqvoc/forms.css.scss +13 -0
  17. data/app/assets/stylesheets/iqvoc/hacks.css.scss +8 -0
  18. data/app/assets/stylesheets/iqvoc/jquery-ui_extensions.css.scss +9 -0
  19. data/app/assets/stylesheets/iqvoc/layout.css.scss +0 -0
  20. data/app/assets/stylesheets/iqvoc/manifest.css +10 -2
  21. data/app/assets/stylesheets/iqvoc/note.css.scss +64 -0
  22. data/app/assets/stylesheets/iqvoc/panel.css.scss +30 -0
  23. data/app/assets/stylesheets/iqvoc/sidebar.css.scss +8 -0
  24. data/app/assets/stylesheets/iqvoc/visualization.css.scss +46 -0
  25. data/app/controllers/collections_controller.rb +3 -3
  26. data/app/controllers/concepts/untranslated_controller.rb +1 -1
  27. data/app/controllers/concepts/versions_controller.rb +8 -7
  28. data/app/controllers/concepts_controller.rb +4 -4
  29. data/app/controllers/instance_configuration_controller.rb +2 -2
  30. data/app/controllers/user_sessions_controller.rb +2 -2
  31. data/app/controllers/users_controller.rb +12 -33
  32. data/app/helpers/application_helper.rb +57 -25
  33. data/app/helpers/concepts_helper.rb +17 -8
  34. data/app/helpers/dashboard_helper.rb +2 -2
  35. data/app/helpers/form_helper.rb +27 -0
  36. data/app/helpers/navigation_helper.rb +58 -0
  37. data/app/helpers/search_results_helper.rb +12 -0
  38. data/app/views/collections/_form.html.erb +27 -21
  39. data/app/views/collections/_header.html.erb +6 -0
  40. data/app/views/collections/_sidebar.html.erb +11 -0
  41. data/app/views/collections/edit.html.erb +3 -9
  42. data/app/views/collections/index.html.erb +3 -8
  43. data/app/views/collections/new.html.erb +4 -5
  44. data/app/views/collections/show.html.erb +20 -20
  45. data/app/views/concepts/_form.html.erb +69 -0
  46. data/app/views/concepts/_header.html.erb +8 -0
  47. data/app/views/concepts/_visualization.html.erb +3 -1
  48. data/app/views/concepts/alphabetical/index.html.erb +13 -14
  49. data/app/views/concepts/edit.html.erb +6 -29
  50. data/app/views/concepts/hierarchical/index.html.erb +4 -4
  51. data/app/views/concepts/new.html.erb +3 -2
  52. data/app/views/concepts/notifications/_referenced_concepts.html.erb +14 -0
  53. data/app/views/concepts/show_published.html.erb +11 -10
  54. data/app/views/concepts/show_unpublished.html.erb +15 -16
  55. data/app/views/concepts/sidebars/_plural.html.erb +18 -0
  56. data/app/views/concepts/sidebars/_singular.html.erb +12 -0
  57. data/app/views/concepts/untranslated/index.html.erb +23 -17
  58. data/app/views/dashboard/_sidebar.html.erb +14 -0
  59. data/app/views/dashboard/index.html.erb +34 -43
  60. data/app/views/import/import.html.erb +6 -3
  61. data/app/views/import/index.html.erb +14 -20
  62. data/app/views/instance_configuration/index.html.erb +5 -9
  63. data/app/views/kaminari/_first_page.html.erb +13 -0
  64. data/app/views/kaminari/_gap.html.erb +8 -0
  65. data/app/views/kaminari/_last_page.html.erb +13 -0
  66. data/app/views/kaminari/_next_page.html.erb +13 -0
  67. data/app/views/kaminari/_page.html.erb +12 -6
  68. data/app/views/kaminari/_paginator.html.erb +11 -1
  69. data/app/views/kaminari/_prev_page.html.erb +13 -0
  70. data/app/views/layouts/_controls.html.erb +19 -16
  71. data/app/views/layouts/_navigation.html.erb +30 -0
  72. data/app/views/layouts/_sections.html.erb +14 -6
  73. data/app/views/layouts/application.html.erb +39 -63
  74. data/app/views/partials/collection/_member.html.erb +2 -4
  75. data/app/views/partials/concept/_new_link_base.html.erb +2 -3
  76. data/app/views/partials/concept/relation/_base.html.erb +2 -2
  77. data/app/views/partials/concept/relation/_edit_base.html.erb +5 -7
  78. data/app/views/partials/concept/relation/_edit_ranked.html.erb +5 -6
  79. data/app/views/partials/concept/relation/_ranked.html.erb +2 -2
  80. data/app/views/partials/concept/relation/skos/_narrower.html.erb +3 -5
  81. data/app/views/partials/concept/relation/skos/broader/_mono.html.erb +4 -6
  82. data/app/views/partials/concept/relation/skos/broader/_poly.html.erb +3 -6
  83. data/app/views/partials/labeling/skos/_base.html.erb +7 -7
  84. data/app/views/partials/labeling/skos/_edit_base.html.erb +11 -7
  85. data/app/views/partials/match/_base.html.erb +2 -2
  86. data/app/views/partials/match/_edit_base.html.erb +5 -6
  87. data/app/views/partials/note/_base.html.erb +12 -14
  88. data/app/views/partials/note/_edit_base.html.erb +7 -17
  89. data/app/views/partials/note/_note.html.erb +13 -11
  90. data/app/views/partials/note/skos/_edit_change_note.html.erb +28 -37
  91. data/app/views/search_results/_header.html.erb +8 -0
  92. data/app/views/search_results/_sidebar.html.erb +7 -0
  93. data/app/views/search_results/index.html.erb +54 -70
  94. data/app/views/user_sessions/_form.html.erb +6 -8
  95. data/app/views/user_sessions/new.html.erb +2 -2
  96. data/app/views/users/_form.html.erb +14 -45
  97. data/app/views/users/_sidebar.html.erb +5 -0
  98. data/app/views/users/edit.html.erb +3 -14
  99. data/app/views/users/index.html.erb +25 -25
  100. data/app/views/users/new.html.erb +3 -13
  101. data/config/engine.rb +3 -0
  102. data/config/initializers/simple_form.rb +177 -0
  103. data/config/locales/activerecord.de.yml +5 -0
  104. data/config/locales/activerecord.en.yml +5 -0
  105. data/config/locales/authlogic.en.yml +2 -2
  106. data/config/locales/de.yml +27 -20
  107. data/config/locales/en.yml +25 -17
  108. data/config/locales/simple_form.en.yml +24 -0
  109. data/iqvoc.gemspec +2 -0
  110. data/lib/iqvoc/configuration/core.rb +8 -12
  111. data/lib/iqvoc/version.rb +1 -1
  112. data/lib/templates/erb/scaffold/_form.html.erb +13 -0
  113. data/test/integration/browse_concepts_and_labels_test.rb +2 -2
  114. data/test/integration/client_edit_concept_test.rb +3 -3
  115. data/test/integration/collection_circularity_test.rb +1 -1
  116. data/test/integration/concept_test.rb +0 -1
  117. data/test/integration/edit_concepts_test.rb +1 -1
  118. data/test/integration/instance_configuration_test.rb +4 -5
  119. data/test/integration/note_annotations_test.rb +2 -2
  120. data/test/integration/search_test.rb +15 -15
  121. data/test/integration/tree_test.rb +1 -1
  122. data/test/integration/untranslated_test.rb +1 -2
  123. data/test/integration_test_helper.rb +0 -12
  124. data/vendor/assets/images/bootstrap/glyphicons-halflings-white.png +0 -0
  125. data/vendor/assets/images/bootstrap/glyphicons-halflings.png +0 -0
  126. data/vendor/assets/javascripts/bootstrap/bootstrap.js +1824 -0
  127. data/vendor/assets/javascripts/html5.js +3 -0
  128. data/vendor/assets/stylesheets/bootstrap/bootstrap-responsive.css +808 -0
  129. data/vendor/assets/stylesheets/bootstrap/bootstrap.css +4960 -0
  130. metadata +84 -65
  131. data/app/assets/images/back.png +0 -0
  132. data/app/assets/images/branch.png +0 -0
  133. data/app/assets/images/categ.png +0 -0
  134. data/app/assets/images/categ_open.png +0 -0
  135. data/app/assets/images/footer.png +0 -0
  136. data/app/assets/images/go_there.png +0 -0
  137. data/app/assets/images/header_long.png +0 -0
  138. data/app/assets/images/iqvoc.png +0 -0
  139. data/app/assets/images/leaf_end.png +0 -0
  140. data/app/assets/images/leaf_end_filled.png +0 -0
  141. data/app/assets/images/leaf_mid.png +0 -0
  142. data/app/assets/images/leaf_mid_filled.png +0 -0
  143. data/app/assets/images/leaf_nothing.png +0 -0
  144. data/app/assets/images/leaf_only.png +0 -0
  145. data/app/assets/images/leaf_only_filled.png +0 -0
  146. data/app/assets/images/leaf_top.png +0 -0
  147. data/app/assets/images/leaf_top_filled.png +0 -0
  148. data/app/assets/images/nothing.png +0 -0
  149. data/app/assets/images/ok.png +0 -0
  150. data/app/assets/images/rdf_flyer.gif +0 -0
  151. data/app/assets/images/red_arrow.png +0 -0
  152. data/app/assets/images/shadow.png +0 -0
  153. data/app/assets/images/spinner.gif +0 -0
  154. data/app/assets/images/tokenizer_delete.png +0 -0
  155. data/app/assets/images/tokenizer_pencile.png +0 -0
  156. data/app/assets/images/tokenizer_show.png +0 -0
  157. data/app/assets/images/top_01.png +0 -0
  158. data/app/assets/images/trunk.png +0 -0
  159. data/app/assets/images/unfinished.png +0 -0
  160. data/app/assets/stylesheets/iqvoc/forms.css.erb +0 -75
  161. data/app/assets/stylesheets/iqvoc/iqvoc.css.erb +0 -492
  162. data/app/assets/stylesheets/iqvoc/widgets.css +0 -81
  163. data/app/controllers/pages_controller.rb +0 -21
  164. data/app/views/concepts/_base_data.html.erb +0 -80
  165. data/app/views/concepts/_close_match.html.erb +0 -16
  166. data/app/views/concepts/_show_head.html.erb +0 -23
  167. data/app/views/pages/about.html.erb +0 -79
  168. data/app/views/partials/_rdf_logo.html.erb +0 -3
  169. data/app/views/search_results/_head_contents.html.erb +0 -4
  170. data/app/views/search_results/_rdf_links.html.erb +0 -4
  171. data/test/integration/browse_static_pages_test.rb +0 -28
  172. data/vendor/assets/stylesheets/blueprint/ie.css +0 -35
  173. data/vendor/assets/stylesheets/blueprint/print.css +0 -29
  174. data/vendor/assets/stylesheets/blueprint/screen.css +0 -258
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 4.0.0 (2012-05-31)
2
+
3
+ * Completely redesigned UI
4
+ * Temporarily removed visualization graph<br>
5
+ Needs to be revisited in the near future
6
+ * Bugfixes
7
+
1
8
  ## 3.5.7 (2012-05-24)
2
9
 
3
10
  * Rankable (weighted) relations
data/Gemfile CHANGED
@@ -22,7 +22,8 @@ source 'http://rubygems.org'
22
22
  gem 'rails', '3.2.3'
23
23
 
24
24
  group :assets do
25
- gem 'uglifier', '>= 1.0.3'
25
+ gem 'uglifier', '>= 1.0.3'
26
+ gem 'sass-rails', '~> 3.2.5'
26
27
  gem 'therubyracer', :platforms => :ruby
27
28
  end
28
29
 
@@ -33,6 +34,7 @@ gem 'iq_rdf', '~> 0.1.2'
33
34
  gem 'json'
34
35
  gem 'rails_autolink'
35
36
  gem 'jruby-openssl', :platforms => :jruby
37
+ gem 'simple_form'
36
38
  gem 'fastercsv', :platforms => :ruby_18
37
39
 
38
40
  group :development do
@@ -57,6 +59,7 @@ end
57
59
  group :test do
58
60
  gem 'nokogiri', '~> 1.5.0'
59
61
  gem 'capybara'
62
+ gem 'capybara-screenshot'
60
63
  gem 'capybara-webkit'
61
64
  gem 'database_cleaner'
62
65
  gem 'factory_girl_rails'
data/Gemfile.lock CHANGED
@@ -22,14 +22,6 @@ GEM
22
22
  activesupport (= 3.2.3)
23
23
  arel (~> 3.0.2)
24
24
  tzinfo (~> 0.3.29)
25
- activerecord-jdbc-adapter (1.2.2)
26
- activerecord-jdbcmysql-adapter (1.2.2)
27
- activerecord-jdbc-adapter (~> 1.2.2)
28
- jdbc-mysql (~> 5.1.0)
29
- activerecord-jdbcsqlite3-adapter (1.2.2)
30
- activerecord-jdbc-adapter (~> 1.2.2)
31
- jdbc-sqlite3 (~> 3.7.2)
32
- activerecord-oracle_enhanced-adapter (1.4.1)
33
25
  activeresource (3.2.3)
34
26
  activemodel (= 3.2.3)
35
27
  activesupport (= 3.2.3)
@@ -43,7 +35,6 @@ GEM
43
35
  activerecord (>= 3.0.7)
44
36
  activerecord (>= 3.0.7)
45
37
  awesome_print (1.0.2)
46
- bouncy-castle-java (1.5.0146.1)
47
38
  builder (3.0.0)
48
39
  cancan (1.6.7)
49
40
  capybara (1.1.2)
@@ -53,6 +44,8 @@ GEM
53
44
  rack-test (>= 0.5.4)
54
45
  selenium-webdriver (~> 2.0)
55
46
  xpath (~> 0.1.4)
47
+ capybara-screenshot (0.1.10)
48
+ capybara (>= 1.0)
56
49
  capybara-webkit (0.12.0)
57
50
  capybara (>= 1.0.0, < 1.2)
58
51
  json
@@ -69,7 +62,6 @@ GEM
69
62
  railties (>= 3.0.0)
70
63
  fastercsv (1.5.5)
71
64
  ffi (1.0.11)
72
- ffi (1.0.11-java)
73
65
  heroku (2.25.0)
74
66
  launchy (>= 0.3.2)
75
67
  netrc (~> 0.7.1)
@@ -80,23 +72,14 @@ GEM
80
72
  iq_rdf (0.1.5)
81
73
  builder
82
74
  bundler
83
- jdbc-mysql (5.1.13)
84
- jdbc-sqlite3 (3.7.2)
85
75
  journey (1.0.3)
86
- jruby-openssl (0.7.6.1)
87
- bouncy-castle-java (>= 1.5.0146.1)
88
76
  json (1.7.3)
89
- json (1.7.3-java)
90
77
  kaminari (0.13.0)
91
78
  actionpack (>= 3.0.0)
92
79
  activesupport (>= 3.0.0)
93
80
  railties (>= 3.0.0)
94
81
  launchy (2.1.0)
95
82
  addressable (~> 2.2.6)
96
- launchy (2.1.0-java)
97
- addressable (~> 2.2.6)
98
- ffi (~> 1.0.9)
99
- spoon (~> 0.0.1)
100
83
  libv8 (3.3.10.4)
101
84
  libwebsocket (0.1.3)
102
85
  addressable
@@ -110,7 +93,6 @@ GEM
110
93
  mysql2 (0.3.11)
111
94
  netrc (0.7.1)
112
95
  nokogiri (1.5.2)
113
- nokogiri (1.5.2-java)
114
96
  pg (0.13.2)
115
97
  polyglot (0.3.3)
116
98
  rack (1.4.1)
@@ -143,13 +125,20 @@ GEM
143
125
  rest-client (1.6.7)
144
126
  mime-types (>= 1.16)
145
127
  rubyzip (0.9.8)
128
+ sass (3.1.18)
129
+ sass-rails (3.2.5)
130
+ railties (~> 3.2.0)
131
+ sass (>= 3.1.10)
132
+ tilt (~> 1.3)
146
133
  selenium-webdriver (2.21.2)
147
134
  childprocess (>= 0.2.5)
148
135
  ffi (~> 1.0)
149
136
  libwebsocket (~> 0.1.3)
150
137
  multi_json (~> 1.0)
151
138
  rubyzip
152
- spoon (0.0.1)
139
+ simple_form (2.0.2)
140
+ actionpack (~> 3.0)
141
+ activemodel (~> 3.0)
153
142
  spork (0.9.2)
154
143
  spork-testunit (0.0.8)
155
144
  spork (>= 0.6.0)
@@ -177,7 +166,6 @@ GEM
177
166
  nokogiri (~> 1.3)
178
167
 
179
168
  PLATFORMS
180
- java
181
169
  ruby
182
170
 
183
171
  DEPENDENCIES
@@ -188,6 +176,7 @@ DEPENDENCIES
188
176
  awesome_print
189
177
  cancan
190
178
  capybara
179
+ capybara-screenshot
191
180
  capybara-webkit
192
181
  database_cleaner
193
182
  factory_girl_rails
@@ -203,6 +192,8 @@ DEPENDENCIES
203
192
  pg
204
193
  rails (= 3.2.3)
205
194
  rails_autolink
195
+ sass-rails (~> 3.2.5)
196
+ simple_form
206
197
  spork
207
198
  spork-testunit
208
199
  sqlite3
Binary file
Binary file
Binary file
@@ -5,3 +5,4 @@
5
5
  //= require jquery.treeview
6
6
  //= require jquery.treeview.async
7
7
  //= require storage
8
+ //= require bootstrap/bootstrap
@@ -6,115 +6,115 @@ IQVOC.EntitySelector = (function($) {
6
6
  "use strict";
7
7
 
8
8
  var EntitySelector = function(node) {
9
- if(arguments.length === 0) { // subclassing; skip initialization
10
- return;
11
- }
12
- this.el = $(node).hide(); // XXX: rename
13
- this.container = $('<div class="entity_select" />').data("widget", this);
14
- this.delimiter = ",";
15
- this.singular = this.el.data("singular") || false;
16
- this.entities = this.getSelection();
17
- this.uriTemplate = this.el.data("entity-uri");
9
+ if(arguments.length === 0) { // subclassing; skip initialization
10
+ return;
11
+ }
12
+ this.el = $(node).hide(); // XXX: rename
13
+ this.container = $('<div class="entity_select" />').data("widget", this);
14
+ this.delimiter = ",";
15
+ this.singular = this.el.data("singular") || false;
16
+ this.entities = this.getSelection();
17
+ this.uriTemplate = this.el.data("entity-uri");
18
18
 
19
- var self = this;
19
+ var self = this;
20
20
 
21
- var selection = $.map(this.el.data("entities"), function(entity, i) {
22
- return self.createEntity(entity);
23
- });
24
- selection = $('<ul class="entity_list" />').append(selection);
21
+ var selection = $.map(this.el.data("entities"), function(entity, i) {
22
+ return self.createEntity(entity);
23
+ });
24
+ selection = $('<ul class="entity_list" />').append(selection);
25
25
 
26
- var exclude = this.el.data("exclude") || null,
27
- img = $('<img class="hidden" />').
28
- attr("src", "<%= asset_path('spinner.gif') %>");
29
- this.input = $("<input />").autocomplete({
30
- minLength: 3,
31
- source: function(req, callback) {
32
- var uri = self.el.data("query-url");
33
- $.getJSON(uri, { query: req.term }, function(data, status, xhr) { // TODO: error handling
34
- var excludes = self.getSelection().
35
- concat(exclude ? [exclude] : []);
36
- data = $.map(data, function(entity, i) {
37
- return $.inArray(entity.id, excludes) !== -1 ? null :
38
- { value: entity.id, label: entity.name };
39
- });
40
- self.input.autocomplete("option", "autoFocus", data.length === 1);
41
- callback(data);
42
- img.addClass("hidden");
43
- });
44
- },
45
- search: function(ev, ui) { img.removeClass("hidden"); },
46
- focus: function(ev, ui) { return false; },
47
- select: this.onSelect
48
- });
26
+ var exclude = this.el.data("exclude") || null,
27
+ img = $('<img class="spinner hidden" />').
28
+ attr("src", "<%= asset_path('spinner_16x16.gif') %>");
29
+ this.input = $("<input />").autocomplete({
30
+ minLength: 3,
31
+ source: function(req, callback) {
32
+ var uri = self.el.data("query-url");
33
+ $.getJSON(uri, { query: req.term }, function(data, status, xhr) { // TODO: error handling
34
+ var excludes = self.getSelection().
35
+ concat(exclude ? [exclude] : []);
36
+ data = $.map(data, function(entity, i) {
37
+ return $.inArray(entity.id, excludes) !== -1 ? null :
38
+ { value: entity.id, label: entity.name };
39
+ });
40
+ self.input.autocomplete("option", "autoFocus", data.length === 1);
41
+ callback(data);
42
+ img.addClass("hidden");
43
+ });
44
+ },
45
+ search: function(ev, ui) { img.removeClass("hidden"); },
46
+ focus: function(ev, ui) { return false; },
47
+ select: this.onSelect
48
+ });
49
49
 
50
- this.container.append(this.input).append(img).append(selection).
51
- insertAfter(node).prepend(node);
50
+ this.container.append(this.input).append(img).append(selection).
51
+ insertAfter(node).prepend(node);
52
52
 
53
- if(this.singular && this.entities.length) {
54
- this.input.hide();
55
- }
53
+ if(this.singular && this.entities.length) {
54
+ this.input.hide();
55
+ }
56
56
  };
57
57
  $.extend(EntitySelector.prototype, {
58
- onSelect: function(ev, ui) {
59
- var el = $(this).val(""),
60
- widget = el.closest(".entity_select").data("widget");
61
- if(widget.add(ui.item.value)) {
62
- var entity = widget.
63
- createEntity({ id: ui.item.value, name: ui.item.label });
64
- widget.container.find("ul").append(entity);
65
- if(widget.singular) {
66
- widget.input.hide();
67
- }
68
- }
69
- return false;
70
- },
71
- onDelete: function(ev) {
72
- var el = $(this),
73
- entity = el.closest("li"),
74
- widget = el.closest(".entity_select").data("widget");
75
- widget.remove(entity.data("id"));
76
- entity.remove();
77
- if(widget.singular && !widget.entities.length) {
78
- widget.input.show();
79
- }
80
- ev.preventDefault();
81
- },
82
- createEntity: function(entity) {
83
- var el;
84
- if(this.uriTemplate) {
85
- var uri = this.uriTemplate.replace("%7Bid%7D", entity.id); // XXX: not very generic
86
- el = $('<a target="_blank" />').attr("href", uri).text(entity.name);
87
- } else {
88
- el = $('<span />').text(entity.name);
89
- }
90
- var delBtn = $('<a href="javascript:;" class="btn">x</a>'). // "btn" to avoid fancy "button" class -- XXX: hacky workaround!?
91
- click(this.onDelete);
92
- return $("<li />").data("id", entity.id).append(el).append(delBtn)[0];
93
- },
94
- add: function(entity) {
95
- if($.inArray(entity, this.entities) === -1) {
96
- this.entities.push(entity);
97
- this.setSelection();
98
- return true;
99
- } else {
100
- return false;
101
- }
102
- },
103
- remove: function(entity) {
104
- var pos = $.inArray(entity, this.entities);
105
- if(pos !== -1) {
106
- this.entities.splice(pos, 1);
107
- this.setSelection();
108
- }
109
- },
110
- setSelection: function() {
111
- this.el.val(this.entities.join(this.delimiter));
112
- },
113
- getSelection: function() {
114
- return $.map(this.el.val().split(this.delimiter), function(entity, i) {
115
- return entity ? $.trim(entity) : null;
116
- });
117
- }
58
+ onSelect: function(ev, ui) {
59
+ var el = $(this).val(""),
60
+ widget = el.closest(".entity_select").data("widget");
61
+ if(widget.add(ui.item.value)) {
62
+ var entity = widget.
63
+ createEntity({ id: ui.item.value, name: ui.item.label });
64
+ widget.container.find("ul").append(entity);
65
+ if(widget.singular) {
66
+ widget.input.hide();
67
+ }
68
+ }
69
+ return false;
70
+ },
71
+ onDelete: function(ev) {
72
+ var el = $(this),
73
+ entity = el.closest("li"),
74
+ widget = el.closest(".entity_select").data("widget");
75
+ widget.remove(entity.data("id"));
76
+ entity.remove();
77
+ if(widget.singular && !widget.entities.length) {
78
+ widget.input.show();
79
+ }
80
+ ev.preventDefault();
81
+ },
82
+ createEntity: function(entity) {
83
+ var el;
84
+ if(this.uriTemplate) {
85
+ var uri = this.uriTemplate.replace("%7Bid%7D", entity.id); // XXX: not very generic
86
+ el = $('<a target="_blank" />').attr("href", uri).text(entity.name);
87
+ } else {
88
+ el = $('<span />').text(entity.name);
89
+ }
90
+ var delBtn = $('<a href="javascript:;" class="remove_entity">x</a>'). // "btn" to avoid fancy "button" class -- XXX: hacky workaround!?
91
+ click(this.onDelete);
92
+ return $("<li />").data("id", entity.id).append(el).append(delBtn)[0];
93
+ },
94
+ add: function(entity) {
95
+ if($.inArray(entity, this.entities) === -1) {
96
+ this.entities.push(entity);
97
+ this.setSelection();
98
+ return true;
99
+ } else {
100
+ return false;
101
+ }
102
+ },
103
+ remove: function(entity) {
104
+ var pos = $.inArray(entity, this.entities);
105
+ if(pos !== -1) {
106
+ this.entities.splice(pos, 1);
107
+ this.setSelection();
108
+ }
109
+ },
110
+ setSelection: function() {
111
+ this.el.val(this.entities.join(this.delimiter));
112
+ },
113
+ getSelection: function() {
114
+ return $.map(this.el.val().split(this.delimiter), function(entity, i) {
115
+ return entity ? $.trim(entity) : null;
116
+ });
117
+ }
118
118
  });
119
119
 
120
120
  return EntitySelector;
@@ -5,257 +5,201 @@ var IQVOC = (function($) {
5
5
 
6
6
  "use strict";
7
7
 
8
- var dynamicAuth = function(container) {
9
- container = container.nodeType ? container : $(container)[0];
10
- var authLink = $("a", container),
11
- uri = authLink.attr("href");
12
- if(uri.indexOf("/new.html") !== -1) {
13
- var menu = $("ul", container),
14
- label = authLink.text() + " &#9660;";
15
- authLink.click(function(ev) {
16
- authLink.html(label);
17
- menu.removeClass("hidden").slideDown()
18
- .find("li").load(uri + " #new_user_session");
19
- ev.preventDefault();
20
- });
21
- }
22
- };
23
-
24
- var collapseDropdown = function(node) {
25
- var el = $(node || this);
26
- el.find("ul").slideUp(function() {
27
- el.removeClass("hover");
28
- });
29
- };
30
-
31
- // augments Son of Suckerfish drop-down menus
32
- var enhancedDropdown = function(container) {
33
- container = container.jquery ? container : $(container);
34
- var menuItems = $("> li", container),
35
- ddtimer;
36
- menuItems.find("ul").hide();
37
- menuItems.live({
38
- mouseenter: function(ev) {
39
- clearTimeout(ddtimer);
40
- menuItems.not(this).filter(".hover").each(function(i, node) {
41
- collapseDropdown(node);
42
- });
43
- $(this).addClass("hover")
44
- .find("ul").not(".hidden").slideDown();
45
- },
46
- mouseleave: function(ev) {
47
- clearTimeout(ddtimer);
48
- ddtimer = setTimeout(jQuery.proxy(collapseDropdown, this), 600);
49
- }
50
- });
51
- };
52
-
53
8
  var createNote = function(ev) {
54
- var container = $(this).closest("fieldset"),
55
- source = $("ol li:last-child", container);
56
-
57
- // special case for usage notes
58
- // a usage note contains a select box instead of a textarea
59
- // FIXME: Hardcoded UMT stuff
60
- var isUsageNote = source.find("label:first")[0].getAttribute("for");
61
- isUsageNote = isUsageNote ? isUsageNote.match(/^concept_note_umt_usage_notes/) : false;
62
- var noteSelector = isUsageNote ? "select" : "textarea, input";
63
-
64
- if(source.is(":hidden")) {
65
- source.show();
66
- return false;
67
- }
68
-
69
- var clone = source.clone();
70
-
71
- var count = source.find(noteSelector)[0].id
72
- .match(/_(\d+)_/)[1];
73
- count = String(parseInt(count, 10) + 1);
74
- var newIdCount = "_" + count + "_",
75
- newNameCount = "[" + count + "]";
76
-
77
- clone.find("label")[0]
78
- .setAttribute("for", (source.find("label")[0].getAttribute("for") || "")
79
- .replace(/_\d+_/, newIdCount));
80
-
81
- // clone.find("input")
82
- // .attr("id", source.find("input[type=hidden]").attr("id").replace(/_\d+_/, newIdCount))
83
- // .attr("name", source.find("input[type=hidden]").attr("name").replace(/\[\d+\]/, newNameCount));
84
-
85
- var src, el;
86
- if(!isUsageNote) {
87
- src = source.find(noteSelector)[0];
88
- el = clone.find(noteSelector).val("")[0];
89
- el.id = src.id.replace(/_\d+_/, newIdCount);
90
- el.name = src.name.replace(/\[\d+\]/, newNameCount);
91
- }
92
- src = source.find("select")[0];
93
- if(src) {
94
- el = clone.find("select")[0];
95
- el.id = src.id.replace(/_\d+_/, newIdCount);
96
- el.name = src.name.replace(/\[\d+\]/, newNameCount);
97
- }
98
-
99
- clone.addClass("new");
100
- $("ol", container).append(clone);
101
-
102
- return false;
9
+ var addButton = $(this);
10
+ var container = addButton.closest("fieldset");
11
+ var source = $("ol li:last-child", container);
12
+ var inputSelector = "input, select, textarea";
13
+
14
+ if(source.is(":hidden")) {
15
+ source.show();
16
+ return false;
17
+ }
18
+
19
+ var clone = source.clone();
20
+
21
+ var count = source.find(inputSelector)[0].id
22
+ .match(/_(\d+)_/)[1];
23
+ count = String(parseInt(count, 10) + 1);
24
+ var newIdCount = "_" + count + "_",
25
+ newNameCount = "[" + count + "]";
26
+
27
+ clone.find("label").each(function(index, element) {
28
+ var el = $(element);
29
+ if (el.attr("for")) {
30
+ el.attr("for", el.attr("for").replace(/_\d+_/, newIdCount));
31
+ }
32
+ })
33
+
34
+ clone.find(inputSelector).each(function(index, element) {
35
+ var el = $(element);
36
+ el.val("");
37
+ if (el.attr("id")) {
38
+ el.attr("id", el.attr("id").replace(/_\d+_/, newIdCount));
39
+ }
40
+ if (el.attr("name")) {
41
+ el.attr("name", el.attr("name").replace(/\[\d+\]/, newNameCount));
42
+ }
43
+ });
44
+
45
+ clone.addClass("new");
46
+ $("ol", container).append(clone);
47
+
48
+ return false;
103
49
  };
104
50
 
105
51
  // work around apparent capybara-webkit issue:
106
52
  // https://github.com/thoughtbot/capybara-webkit/issues/43
107
53
  var Storage = localStorage || null;
108
54
  if(Storage === null) {
109
- Storage = {};
110
- Storage.getItem = function() { return null; };
111
- Storage.setItem = $.noop;
55
+ Storage = {};
56
+ Storage.getItem = function() { return null; };
57
+ Storage.setItem = $.noop;
112
58
  }
113
59
 
114
60
  return {
115
- Storage: Storage,
116
- dynamicAuth: dynamicAuth,
117
- enhancedDropdown: enhancedDropdown,
118
- createNote: createNote
61
+ Storage: Storage,
62
+ createNote: createNote
119
63
  };
120
64
 
121
65
  }(jQuery));
122
66
 
123
67
  jQuery(document).ready(function($) {
124
- "use strict";
125
-
126
- var locale = document.documentElement.getAttribute("lang");
127
-
128
- IQVOC.enhancedDropdown(".menu");
129
- IQVOC.dynamicAuth("#auth_controls");
130
-
131
- if(IQVOC.visualization) {
132
- IQVOC.visualization.init("infovis", function(container) {
133
- if(IQVOC.Storage.getItem("visualization") === "enlarged") {
134
- container.data("widget").toggleSize(true);
135
- }
136
- });
137
- }
138
-
139
- // language selection
140
- var langWidget = $("ul.lang-widget")[0];
141
- // primary language (converting links to radio buttons)
142
- $("a", langWidget).each(function(i, node) {
143
- var link = $(node),
144
- el = link.closest("li"),
145
- btn = $('<input type="radio" name="primary_language">');
146
- if(link.hasClass("current")) {
147
- btn[0].checked = true;
148
- }
149
- var label = $("<label />").append(btn).append(link);
150
- el.append(label);
151
- return label[0];
152
- });
153
- $("input:radio", langWidget).live("change", function(ev) {
154
- window.location = $(this).closest("label").find("a").attr("href");
155
- });
156
- // secondary language
157
- var toggleSections = function(langSelected) {
158
- $(".translation[lang]").each(function(i, node) {
159
- var el = $(node),
160
- lang = el.attr("lang");
161
- if(lang !== locale && $.inArray(lang, langSelected) === -1) {
162
- el.addClass("hidden");
163
- } else {
164
- el.removeClass("hidden");
165
- }
166
- });
167
- };
168
- var updateNoteLangs = function(langSelected) {
169
- $(".inline_note.new select").each(function(i, sel) { // NB: new notes only!
170
- $(sel).find("option").each(function(i, opt) {
171
- var el = $(opt),
172
- lang = el.val();
173
- if(lang !== locale && $.inArray(lang, langSelected) === -1) {
174
- el.remove();
175
- }
176
- });
177
- });
178
- };
179
- $(document).bind("lang_selected", function(ev, data) {
180
- toggleSections(data.langs);
181
- updateNoteLangs(data.langs);
182
- });
183
- var langSelector = new IQVOC.LanguageSelector(langWidget, "lang_selected");
184
- if($("#new_concept, #edit_concept").length) { // edit mode
185
- // disable secondary language selection to avoid excessive state complexity
186
- $(":checkbox", langSelector.container).prop("disabled", true);
187
- }
188
-
189
- // entity selection (edit mode)
190
- $("input.entity_select").each(function(i, node) {
191
- new IQVOC.QualifiedEntitySelector(node);
192
- });
193
-
194
- // hide broader relations for top terms (mutually exclusive in mono hierarchies)
195
- var topTerm = $("#concept_top_term.exclusive");
196
- var onTopTermToggle = function(ev) {
197
- var broader = topTerm.closest("li").next(); // XXX: brittle
198
- broader[topTerm.prop("checked") ? "slideUp" : "slideDown"]();
199
- };
200
- topTerm.on("change", onTopTermToggle);
201
- onTopTermToggle();
202
-
203
- // Label editing (inline notes)
204
- $("fieldset.note_relation ol li.inline_note.new").hide();
205
- $("fieldset.note_relation input[type=button]").click(function(ev) {
206
- IQVOC.createNote.apply(this, arguments);
207
- langSelector.notify(); // trigger updateNoteLangs -- XXX: hacky!?
208
- });
209
- $("li.inline_note input:checkbox").change(function(ev) {
210
- var action = this.checked ? "addClass" : "removeClass";
211
- $(this).closest("li")[action]("deleted");
212
- });
213
-
214
- // Datepicker
215
- $.datepicker.setDefaults($.datepicker.regional[locale]);
216
- $("input.datepicker").datepicker({ dateFormat: "yy-mm-dd" });
217
-
218
- // Dashboard table row highlighting and click handling
219
- $("tr.highlightable")
220
- .hover(function(ev) {
221
- var action = ev.type === "mouseenter" ? "addClass" : "removeClass";
222
- $(this)[action]("hover");
223
- })
224
- .click(function(ev) {
225
- window.location = $(this).attr("data-url");
226
- });
227
-
228
- // Search
229
- $("button#language_select_all").click(function() {
230
- $("input[type=checkbox].lang_check").attr("checked", true);
231
- });
232
- $("button#language_select_none").click(function() {
233
- $("input[type=checkbox].lang_check").attr("checked", false);
234
- });
235
- $("select.search_type").change(function() {
236
- var result_type_filter = $("li.result_type_filter");
237
- if($(this).val().match(/labeling/)) {
238
- result_type_filter.show();
239
- }
240
- else {
241
- result_type_filter.hide();
242
- }
243
- });
244
- $("select.search_type").change();
245
-
246
- // hierarchical tree view
247
- $("ul.hybrid-treeview").each(function() {
248
- var url = $(this).attr("data-url"),
249
- container = this;
250
- $(this).treeview({
251
- collapsed: true,
252
- toggle: function() {
253
- var el = $(this);
254
- if(el.hasClass("hasChildren")) {
255
- var childList = el.removeClass("hasChildren").find("ul");
256
- $.fn.treeviewLoad({ url: url }, this.id, childList, container);
257
- }
258
- }
259
- });
260
- });
68
+ "use strict";
69
+
70
+ var locale = document.documentElement.getAttribute("lang");
71
+
72
+ if(IQVOC.visualization) {
73
+ IQVOC.visualization.init("infovis", function(container) {
74
+ if(IQVOC.Storage.getItem("visualization") === "enlarged") {
75
+ container.data("widget").toggleSize(true);
76
+ }
77
+ });
78
+ }
79
+
80
+ // language selection
81
+ $("#language_selection .dropdown-toggle").click(function(ev) { // use Bootstrap's Dropwdown, but without the side-effects
82
+ $(this).closest(".dropdown").toggleClass("open");
83
+ });
84
+ var langWidget = $("ul.lang-widget")[0];
85
+ // primary language (converting links to radio buttons)
86
+ $("a", langWidget).each(function(i, node) {
87
+ var link = $(node),
88
+ el = link.closest("li"),
89
+ btn = $('<input type="radio" name="primary_language">');
90
+ if(link.hasClass("current")) {
91
+ btn[0].checked = true;
92
+ }
93
+ var label = $("<label />").append(btn).append(link);
94
+ el.append(label);
95
+ return label[0];
96
+ });
97
+ $("input:radio", langWidget).live("change", function(ev) {
98
+ window.location = $(this).closest("label").find("a").attr("href");
99
+ });
100
+ // secondary language
101
+ var toggleSections = function(langSelected) {
102
+ $(".translation[lang]").each(function(i, node) {
103
+ var el = $(node),
104
+ lang = el.attr("lang");
105
+ if(lang !== locale && $.inArray(lang, langSelected) === -1) {
106
+ el.addClass("hidden");
107
+ } else {
108
+ el.removeClass("hidden");
109
+ }
110
+ });
111
+ };
112
+ var updateNoteLangs = function(langSelected) {
113
+ $(".inline_note.new select").each(function(i, sel) { // NB: new notes only!
114
+ $(sel).find("option").each(function(i, opt) {
115
+ var el = $(opt),
116
+ lang = el.val();
117
+ if(lang !== locale && $.inArray(lang, langSelected) === -1) {
118
+ el.remove();
119
+ }
120
+ });
121
+ });
122
+ };
123
+ $(document).bind("lang_selected", function(ev, data) {
124
+ toggleSections(data.langs);
125
+ updateNoteLangs(data.langs);
126
+ });
127
+ var langSelector = new IQVOC.LanguageSelector(langWidget, "lang_selected");
128
+ if($("#new_concept, #edit_concept").length) { // edit mode
129
+ // disable secondary language selection to avoid excessive state complexity
130
+ $(":checkbox", langSelector.container).prop("disabled", true);
131
+ }
132
+
133
+ // entity selection (edit mode)
134
+ $("input.entity_select").each(function(i, node) {
135
+ new IQVOC.QualifiedEntitySelector(node);
136
+ });
137
+
138
+ // hide broader relations for top+ terms (mutually exclusive in mono hierarchies)
139
+ var topTerm = $("#concept_top_term.exclusive");
140
+ var onTopTermToggle = function(ev) {
141
+ var broader = topTerm.closest(".control-group").next(); // XXX: brittle
142
+ broader[topTerm.prop("checked") ? "slideUp" : "slideDown"]();
143
+ };
144
+ topTerm.on("change", onTopTermToggle);
145
+ onTopTermToggle();
146
+
147
+ // Label editing (inline notes)
148
+ $("fieldset.note_relation ol li.inline_note.new").hide();
149
+ $("fieldset.note_relation input[type=button]").click(function(ev) {
150
+ IQVOC.createNote.apply(this, arguments);
151
+ langSelector.notify(); // trigger updateNoteLangs -- XXX: hacky!?
152
+ });
153
+ $("li.inline_note input:checkbox").change(function(ev) {
154
+ var action = this.checked ? "addClass" : "removeClass";
155
+ $(this).closest("li")[action]("deleted");
156
+ });
157
+
158
+ // Datepicker
159
+ $.datepicker.setDefaults($.datepicker.regional[locale]);
160
+ $("input.datepicker").datepicker({ dateFormat: "yy-mm-dd" });
161
+
162
+ // Dashboard table row highlighting and click handling
163
+ $("tr.highlightable")
164
+ .hover(function(ev) {
165
+ var action = ev.type === "mouseenter" ? "addClass" : "removeClass";
166
+ $(this)[action]("hover");
167
+ })
168
+ .click(function(ev) {
169
+ window.location = $(this).attr("data-url");
170
+ });
171
+
172
+ // Search
173
+ $("button#language_select_all").click(function() {
174
+ $("input[type=checkbox].lang_check").attr("checked", true);
175
+ });
176
+ $("button#language_select_none").click(function() {
177
+ $("input[type=checkbox].lang_check").attr("checked", false);
178
+ });
179
+ $("select.search_type").change(function() {
180
+ var result_type_filter = $(".result_type_filter");
181
+ if($(this).val().match(/labeling/)) {
182
+ result_type_filter.show();
183
+ }
184
+ else {
185
+ result_type_filter.hide();
186
+ }
187
+ });
188
+ $("select.search_type").change();
189
+
190
+ // hierarchical tree view
191
+ $("ul.hybrid-treeview").each(function() {
192
+ var url = $(this).attr("data-url"),
193
+ container = this;
194
+ $(this).treeview({
195
+ collapsed: true,
196
+ toggle: function() {
197
+ var el = $(this);
198
+ if(el.hasClass("hasChildren")) {
199
+ var childList = el.removeClass("hasChildren").find("ul");
200
+ $.fn.treeviewLoad({ url: url }, this.id, childList, container);
201
+ }
202
+ }
203
+ });
204
+ });
261
205
  });