blacklight-spotlight 0.32.0 → 0.33.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (202) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +8 -0
  3. data/app/assets/images/spotlight/default_browse_thumbnail.jpg +0 -0
  4. data/app/assets/javascripts/spotlight/application.js +6 -1
  5. data/app/assets/javascripts/spotlight/blocks/pages_block.js +1 -1
  6. data/app/assets/javascripts/spotlight/blocks/resources_block.js +7 -4
  7. data/app/assets/javascripts/spotlight/blocks/solr_documents_base_block.js +108 -0
  8. data/app/assets/javascripts/spotlight/blocks/solr_documents_block.js +12 -56
  9. data/app/assets/javascripts/spotlight/blocks/solr_documents_carousel_block.js +3 -3
  10. data/app/assets/javascripts/spotlight/blocks/solr_documents_embed_block.js +3 -3
  11. data/app/assets/javascripts/spotlight/blocks/solr_documents_features_block.js +3 -3
  12. data/app/assets/javascripts/spotlight/blocks/solr_documents_grid_block.js +3 -3
  13. data/app/assets/javascripts/spotlight/crop.es6 +205 -0
  14. data/app/assets/javascripts/spotlight/croppable.js +7 -104
  15. data/app/assets/javascripts/spotlight/iiif.es6 +54 -0
  16. data/app/assets/javascripts/spotlight/multi_image_selector.js +34 -16
  17. data/app/assets/javascripts/spotlight/pages.js.erb +1 -1
  18. data/app/assets/javascripts/spotlight/reindex_monitor.js +5 -1
  19. data/app/assets/javascripts/spotlight/search_typeahead.js +33 -47
  20. data/app/assets/javascripts/spotlight/sir-trevor/locales.js +5 -2
  21. data/app/assets/javascripts/spotlight/zpr_links.js.erb +30 -0
  22. data/app/assets/stylesheets/spotlight/_croppable.scss +8 -13
  23. data/app/assets/stylesheets/spotlight/_multi_image_selector.scss +1 -1
  24. data/app/assets/stylesheets/spotlight/_pages.scss +5 -0
  25. data/app/assets/stylesheets/spotlight/typeahead.css +0 -1
  26. data/app/controllers/concerns/spotlight/base.rb +3 -5
  27. data/app/controllers/spotlight/appearances_controller.rb +6 -4
  28. data/app/controllers/spotlight/catalog_controller.rb +10 -0
  29. data/app/controllers/spotlight/contacts_controller.rb +2 -6
  30. data/app/controllers/spotlight/featured_images_controller.rb +26 -0
  31. data/app/controllers/spotlight/pages_controller.rb +3 -2
  32. data/app/controllers/spotlight/resources/iiif_harvester_controller.rb +10 -0
  33. data/app/controllers/spotlight/resources/upload_controller.rb +4 -3
  34. data/app/controllers/spotlight/searches_controller.rb +20 -6
  35. data/app/controllers/spotlight/sites_controller.rb +2 -5
  36. data/app/helpers/spotlight/application_helper.rb +14 -1
  37. data/app/helpers/spotlight/crop_helper.rb +37 -0
  38. data/app/helpers/spotlight/main_app_helpers.rb +13 -0
  39. data/app/helpers/spotlight/meta_helper.rb +10 -20
  40. data/app/models/concerns/spotlight/solr_document.rb +1 -2
  41. data/app/models/concerns/spotlight/solr_document/uploaded_resource.rb +1 -23
  42. data/app/models/sir_trevor_rails/blocks/browse_block.rb +10 -0
  43. data/app/models/sir_trevor_rails/blocks/featured_pages_block.rb +10 -0
  44. data/app/models/sir_trevor_rails/blocks/solr_documents_block.rb +5 -0
  45. data/app/models/spotlight/analytics/ga.rb +1 -1
  46. data/app/models/spotlight/blacklight_configuration.rb +16 -8
  47. data/app/models/spotlight/contact.rb +2 -13
  48. data/app/models/spotlight/contact_image.rb +11 -0
  49. data/app/models/spotlight/exhibit.rb +11 -8
  50. data/app/models/spotlight/exhibit_thumbnail.rb +12 -0
  51. data/app/models/spotlight/feature_page.rb +3 -5
  52. data/app/models/spotlight/featured_image.rb +28 -9
  53. data/app/models/spotlight/home_page.rb +2 -0
  54. data/app/models/spotlight/masthead.rb +5 -11
  55. data/app/models/spotlight/page.rb +5 -0
  56. data/app/models/spotlight/reindex_progress.rb +10 -18
  57. data/app/models/spotlight/reindexing_log_entry.rb +1 -0
  58. data/app/models/spotlight/resources/iiif_harvester.rb +33 -0
  59. data/app/models/spotlight/resources/iiif_manifest.rb +211 -0
  60. data/app/models/spotlight/resources/iiif_service.rb +93 -0
  61. data/app/models/spotlight/resources/upload.rb +1 -2
  62. data/app/models/spotlight/search.rb +5 -34
  63. data/app/presenters/spotlight/iiif_manifest_presenter.rb +79 -0
  64. data/app/serializers/spotlight/exhibit_export_serializer.rb +9 -41
  65. data/app/services/spotlight/carrierwave_file_resolver.rb +3 -1
  66. data/app/services/spotlight/iiif_resource_resolver.rb +73 -0
  67. data/app/services/spotlight/resources/iiif_builder.rb +17 -0
  68. data/app/services/spotlight/upload_solr_document_builder.rb +23 -23
  69. data/app/uploaders/spotlight/attachment_uploader.rb +0 -48
  70. data/app/uploaders/spotlight/featured_image_uploader.rb +2 -16
  71. data/app/views/_user_util_links.html.erb +8 -5
  72. data/app/views/catalog/_save_search.html.erb +4 -2
  73. data/app/views/layouts/spotlight/spotlight.html.erb +5 -1
  74. data/app/views/shared/_masthead.html.erb +1 -1
  75. data/app/views/spotlight/about_pages/_contact_properties.html.erb +1 -1
  76. data/app/views/spotlight/appearances/edit.html.erb +26 -6
  77. data/app/views/spotlight/browse/_search.html.erb +1 -1
  78. data/app/views/spotlight/contacts/_form.html.erb +12 -7
  79. data/app/views/spotlight/dashboards/_reindexing_activity.html.erb +1 -1
  80. data/app/views/spotlight/exhibits/_exhibit_card_front.html.erb +2 -2
  81. data/app/views/spotlight/featured_images/_form.html.erb +12 -15
  82. data/app/views/spotlight/featured_images/_upload_form.html.erb +6 -12
  83. data/app/views/spotlight/metadata_configurations/_metadata_field.html.erb +3 -3
  84. data/app/views/spotlight/pages/_form.html.erb +3 -3
  85. data/app/views/spotlight/pages/edit.html.erb +4 -2
  86. data/app/views/spotlight/resources/iiif/_form.html.erb +9 -0
  87. data/app/views/spotlight/searches/_form.html.erb +3 -3
  88. data/app/views/spotlight/searches/_search.html.erb +4 -2
  89. data/app/views/spotlight/sir_trevor/blocks/_browse_block.html.erb +2 -2
  90. data/app/views/spotlight/sir_trevor/blocks/_featured_pages_block.html.erb +1 -1
  91. data/app/views/spotlight/sir_trevor/blocks/_solr_documents_block.html.erb +7 -2
  92. data/app/views/spotlight/sir_trevor/blocks/_solr_documents_carousel_block.html.erb +4 -2
  93. data/app/views/spotlight/sir_trevor/blocks/_solr_documents_features_block.html.erb +4 -2
  94. data/app/views/spotlight/sir_trevor/blocks/_solr_documents_grid_block.html.erb +4 -2
  95. data/app/views/spotlight/sites/edit.html.erb +1 -1
  96. data/config/locales/spotlight.en.yml +31 -6
  97. data/config/routes.rb +9 -0
  98. data/db/migrate/20160714144125_add_iiif_urls_to_featured_image.rb +9 -0
  99. data/db/migrate/20160718194010_add_iiif_url_to_contact.rb +6 -0
  100. data/db/migrate/20160805143841_add_upload_id_to_resources.rb +6 -0
  101. data/db/migrate/20170204091234_add_theme_to_spotlight_exhibits.rb +5 -0
  102. data/lib/generators/spotlight/install_generator.rb +5 -2
  103. data/lib/generators/spotlight/templates/config/initializers/spotlight_initializer.rb +0 -1
  104. data/lib/generators/spotlight/templates/spotlight.scss +3 -2
  105. data/lib/migration/iiif.rb +82 -0
  106. data/lib/spotlight/engine.rb +22 -10
  107. data/lib/spotlight/version.rb +1 -1
  108. data/lib/tasks/spotlight_tasks.rake +10 -0
  109. data/spec/controllers/spotlight/about_pages_controller_spec.rb +1 -1
  110. data/spec/controllers/spotlight/appearances_controller_spec.rb +31 -18
  111. data/spec/controllers/spotlight/catalog_controller_spec.rb +40 -0
  112. data/spec/controllers/spotlight/contacts_controller_spec.rb +20 -1
  113. data/spec/controllers/spotlight/feature_pages_controller_spec.rb +2 -6
  114. data/spec/controllers/spotlight/featured_images_controller_spec.rb +74 -0
  115. data/spec/controllers/spotlight/home_pages_controller_spec.rb +1 -1
  116. data/spec/controllers/spotlight/searches_controller_spec.rb +3 -1
  117. data/spec/controllers/spotlight/sites_controller_spec.rb +6 -1
  118. data/spec/examples.txt +1118 -1059
  119. data/spec/factories/contact_images.rb +6 -0
  120. data/spec/factories/contacts.rb +4 -1
  121. data/spec/factories/exhibit_thumbnails.rb +6 -0
  122. data/spec/factories/exhibits.rb +4 -0
  123. data/spec/factories/featured_images.rb +1 -0
  124. data/spec/factories/resources.rb +2 -1
  125. data/spec/features/add_contacts_spec.rb +5 -5
  126. data/spec/features/add_iiif_manifest_spec.rb +41 -0
  127. data/spec/features/add_items_spec.rb +2 -2
  128. data/spec/features/autocomplete_typeahead_spec.rb +86 -0
  129. data/spec/features/browse_category_admin_spec.rb +27 -6
  130. data/spec/features/browse_category_spec.rb +2 -2
  131. data/spec/features/create_exhibit_spec.rb +3 -3
  132. data/spec/features/exhibit_masthead_spec.rb +20 -9
  133. data/spec/features/exhibit_themes_spec.rb +25 -0
  134. data/spec/features/home_page_spec.rb +1 -1
  135. data/spec/features/javascript/blocks/solr_documents_block_spec.rb +42 -0
  136. data/spec/features/javascript/blocks/uploaded_items_block_spec.rb +5 -3
  137. data/spec/features/javascript/feature_page_admin_spec.rb +1 -1
  138. data/spec/features/javascript/multi_image_select_spec.rb +5 -6
  139. data/spec/features/javascript/search_config_admin_spec.rb +1 -1
  140. data/spec/features/site_masthead_spec.rb +14 -4
  141. data/spec/fixtures/gk446cj2442-manifest.json +58 -0
  142. data/spec/fixtures/iiif_responses.rb +274 -0
  143. data/spec/fixtures/sample_solr_documents.yml +106 -0
  144. data/spec/helpers/spotlight/crop_helper_spec.rb +9 -0
  145. data/spec/helpers/spotlight/main_app_helpers_spec.rb +45 -0
  146. data/spec/helpers/spotlight/meta_helper_spec.rb +2 -15
  147. data/spec/lib/migration/iiif_spec.rb +70 -0
  148. data/spec/models/spotlight/blacklight_configuration_spec.rb +17 -5
  149. data/spec/models/spotlight/contact_image_spec.rb +9 -0
  150. data/spec/models/spotlight/exhibit_spec.rb +17 -20
  151. data/spec/models/spotlight/exhibit_thumbnail_spec.rb +8 -0
  152. data/spec/models/spotlight/featured_image_spec.rb +59 -10
  153. data/spec/models/spotlight/masthead_spec.rb +33 -17
  154. data/spec/models/spotlight/page_spec.rb +14 -0
  155. data/spec/models/spotlight/reindex_progress_spec.rb +22 -73
  156. data/spec/models/spotlight/resources/iiif_harvester_spec.rb +30 -0
  157. data/spec/models/spotlight/resources/iiif_manifest_spec.rb +107 -0
  158. data/spec/models/spotlight/resources/iiif_service_spec.rb +52 -0
  159. data/spec/models/spotlight/resources/upload_spec.rb +7 -3
  160. data/spec/models/spotlight/search_spec.rb +0 -45
  161. data/spec/models/spotlight/solr_document/uploaded_resource_spec.rb +11 -29
  162. data/spec/presenters/spotlight/iiif_manifest_presenter_spec.rb +123 -0
  163. data/spec/routing/spotlight/exhibit_catalog_spec.rb +4 -0
  164. data/spec/routing/spotlight/featured_images_spec.rb +21 -0
  165. data/spec/serializers/spotlight/exhibit_export_serializer_spec.rb +15 -18
  166. data/spec/services/spotlight/iiif_resource_resolver_spec.rb +90 -0
  167. data/spec/spec_helper.rb +3 -0
  168. data/spec/support/features/test_features_helpers.rb +3 -2
  169. data/spec/support/stub_iiif_response.rb +24 -0
  170. data/spec/support/views/test_view_helpers.rb +1 -0
  171. data/spec/test_app_templates/Gemfile.extra +0 -1
  172. data/spec/uploaders/spotlight/attachment_uploader_spec.rb +24 -0
  173. data/spec/uploaders/spotlight/featured_image_uploader_spec.rb +30 -0
  174. data/spec/views/_user_util_links.html.erb_spec.rb +9 -5
  175. data/spec/views/shared/_masthead.html.erb_spec.rb +5 -2
  176. data/spec/views/spotlight/browse/_search.html.erb_spec.rb +2 -2
  177. data/spec/views/spotlight/contacts/edit.html.erb_spec.rb +4 -7
  178. data/spec/views/spotlight/metadata_configurations/_metadata_field.html.erb_spec.rb +7 -2
  179. data/spec/views/spotlight/pages/edit.html.erb_spec.rb +3 -1
  180. data/spec/views/spotlight/pages/new.html.erb_spec.rb +3 -1
  181. data/spec/views/spotlight/searches/_search.html.erb_spec.rb +3 -2
  182. data/spec/views/spotlight/searches/edit.html.erb_spec.rb +3 -2
  183. data/vendor/assets/javascripts/leaflet-areaselect.js +184 -0
  184. data/vendor/assets/javascripts/leaflet-iiif.js +230 -0
  185. data/vendor/assets/javascripts/leaflet.js +9 -0
  186. data/vendor/assets/javascripts/polyfill.min.js +4 -0
  187. data/vendor/assets/stylesheets/leaflet-areaselect.css +15 -0
  188. data/vendor/assets/stylesheets/leaflet.css +624 -0
  189. metadata +136 -62
  190. data/app/assets/javascripts/spotlight/jcrop.js +0 -1696
  191. data/app/helpers/spotlight/jcrop_helper.rb +0 -37
  192. data/app/models/concerns/spotlight/default_thumbnailable.rb +0 -25
  193. data/app/models/concerns/spotlight/image_derivatives.rb +0 -58
  194. data/app/models/concerns/spotlight/solr_document/spotlight_images.rb +0 -55
  195. data/app/uploaders/spotlight/avatar_uploader.rb +0 -24
  196. data/app/uploaders/spotlight/item_uploader.rb +0 -25
  197. data/app/uploaders/spotlight/masthead_uploader.rb +0 -22
  198. data/spec/helpers/spotlight/jcrop_helper_spec.rb +0 -33
  199. data/spec/models/spotlight/default_thumbnailable_concern_spec.rb +0 -16
  200. data/spec/models/spotlight/image_derivatives_spec.rb +0 -15
  201. data/spec/models/spotlight/solr_document/spotlight_images_spec.rb +0 -42
  202. data/spec/uploaders/spotlight/item_uploader_spec.rb +0 -67
@@ -1,1696 +0,0 @@
1
- /**
2
- * jquery.Jcrop.js v0.9.12
3
- * jQuery Image Cropping Plugin - released under MIT License
4
- * Author: Kelly Hallman <khallman@gmail.com>
5
- * http://github.com/tapmodo/Jcrop
6
- * Copyright (c) 2008-2013 Tapmodo Interactive LLC {{{
7
- *
8
- * Permission is hereby granted, free of charge, to any person
9
- * obtaining a copy of this software and associated documentation
10
- * files (the "Software"), to deal in the Software without
11
- * restriction, including without limitation the rights to use,
12
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
13
- * copies of the Software, and to permit persons to whom the
14
- * Software is furnished to do so, subject to the following
15
- * conditions:
16
- *
17
- * The above copyright notice and this permission notice shall be
18
- * included in all copies or substantial portions of the Software.
19
- *
20
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27
- * OTHER DEALINGS IN THE SOFTWARE.
28
- *
29
- * }}}
30
- *
31
- * This is a fork of the above mentioned code which is available at https://github.com/sul-dlss/Jcrop
32
- */
33
-
34
- (function ($) {
35
-
36
- $.Jcrop = function (obj, opt) {
37
- var options = $.extend({}, $.Jcrop.defaults),
38
- docOffset,
39
- _ua = navigator.userAgent.toLowerCase(),
40
- is_msie = /msie/.test(_ua),
41
- ie6mode = /msie [1-6]\./.test(_ua);
42
-
43
- // Internal Methods {{{
44
- function px(n) {
45
- return Math.round(n) + 'px';
46
- }
47
- function cssClass(cl) {
48
- return options.baseClass + '-' + cl;
49
- }
50
- function supportsColorFade() {
51
- return $.fx.step.hasOwnProperty('backgroundColor');
52
- }
53
- function getPos(obj) //{{{
54
- {
55
- var pos = $(obj).offset();
56
- return [pos.left, pos.top];
57
- }
58
- //}}}
59
- function mouseAbs(e) //{{{
60
- {
61
- return [(e.pageX - docOffset[0]), (e.pageY - docOffset[1])];
62
- }
63
- //}}}
64
- function setOptions(opt) //{{{
65
- {
66
- if (typeof(opt) !== 'object') opt = {};
67
- options = $.extend(options, opt);
68
-
69
- $.each(['onChange','onSelect','onRelease','onDblClick'],function(i,e) {
70
- if (typeof(options[e]) !== 'function') options[e] = function () {};
71
- });
72
- }
73
- //}}}
74
- function startDragMode(mode, pos, touch) //{{{
75
- {
76
- docOffset = getPos($img);
77
- Tracker.setCursor(mode === 'move' ? mode : mode + '-resize');
78
-
79
- if (mode === 'move') {
80
- return Tracker.activateHandlers(createMover(pos), doneSelect, touch);
81
- }
82
-
83
- var fc = Coords.getFixed();
84
- var opp = oppLockCorner(mode);
85
- var opc = Coords.getCorner(oppLockCorner(opp));
86
-
87
- Coords.setPressed(Coords.getCorner(opp));
88
- Coords.setCurrent(opc);
89
-
90
- Tracker.activateHandlers(dragmodeHandler(mode, fc), doneSelect, touch);
91
- }
92
- //}}}
93
- function dragmodeHandler(mode, f) //{{{
94
- {
95
- return function (pos) {
96
- if (!options.aspectRatio) {
97
- switch (mode) {
98
- case 'e':
99
- pos[1] = f.y2;
100
- break;
101
- case 'w':
102
- pos[1] = f.y2;
103
- break;
104
- case 'n':
105
- pos[0] = f.x2;
106
- break;
107
- case 's':
108
- pos[0] = f.x2;
109
- break;
110
- }
111
- } else {
112
- switch (mode) {
113
- case 'e':
114
- pos[1] = f.y + 1;
115
- break;
116
- case 'w':
117
- pos[1] = f.y + 1;
118
- break;
119
- case 'n':
120
- pos[0] = f.x + 1;
121
- break;
122
- case 's':
123
- pos[0] = f.x + 1;
124
- break;
125
- }
126
- }
127
- Coords.setCurrent(pos);
128
- Selection.update();
129
- };
130
- }
131
- //}}}
132
- function createMover(pos) //{{{
133
- {
134
- var lloc = pos;
135
- KeyManager.watchKeys();
136
-
137
- return function (pos) {
138
- Coords.moveOffset([pos[0] - lloc[0], pos[1] - lloc[1]]);
139
- lloc = pos;
140
-
141
- Selection.update();
142
- };
143
- }
144
- //}}}
145
- function oppLockCorner(ord) //{{{
146
- {
147
- switch (ord) {
148
- case 'n':
149
- return 'sw';
150
- case 's':
151
- return 'nw';
152
- case 'e':
153
- return 'nw';
154
- case 'w':
155
- return 'ne';
156
- case 'ne':
157
- return 'sw';
158
- case 'nw':
159
- return 'se';
160
- case 'se':
161
- return 'nw';
162
- case 'sw':
163
- return 'ne';
164
- }
165
- }
166
- //}}}
167
- function createDragger(ord) //{{{
168
- {
169
- return function (e) {
170
- if (options.disabled) {
171
- return false;
172
- }
173
- if ((ord === 'move') && !options.allowMove) {
174
- return false;
175
- }
176
-
177
- // Fix position of crop area when dragged the very first time.
178
- // Necessary when crop image is in a hidden element when page is loaded.
179
- docOffset = getPos($img);
180
-
181
- btndown = true;
182
- startDragMode(ord, mouseAbs(e));
183
- e.stopPropagation();
184
- e.preventDefault();
185
- return false;
186
- };
187
- }
188
- //}}}
189
- function presize($obj, w, h) //{{{
190
- {
191
- var nw = $obj.width(),
192
- nh = $obj.height();
193
- if ((nw > w) && w > 0) {
194
- nw = w;
195
- nh = (w / $obj.width()) * $obj.height();
196
- }
197
- if ((nh > h) && h > 0) {
198
- nh = h;
199
- nw = (h / $obj.height()) * $obj.width();
200
- }
201
- xscale = $obj.width() / nw;
202
- yscale = $obj.height() / nh;
203
- $obj.width(nw).height(nh);
204
- }
205
- //}}}
206
- function unscale(c) //{{{
207
- {
208
- return {
209
- x: c.x * xscale,
210
- y: c.y * yscale,
211
- x2: c.x2 * xscale,
212
- y2: c.y2 * yscale,
213
- w: c.w * xscale,
214
- h: c.h * yscale
215
- };
216
- }
217
- //}}}
218
- function doneSelect(pos) //{{{
219
- {
220
- var c = Coords.getFixed();
221
- if ((c.w > options.minSelect[0]) && (c.h > options.minSelect[1])) {
222
- Selection.enableHandles();
223
- Selection.done();
224
- } else {
225
- Selection.release();
226
- }
227
- Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default');
228
- }
229
- //}}}
230
- function newSelection(e) //{{{
231
- {
232
- if (options.disabled) {
233
- return;
234
- }
235
- if (!options.allowSelect) {
236
- return;
237
- }
238
- btndown = true;
239
- docOffset = getPos($img);
240
- Selection.disableHandles();
241
- Tracker.setCursor('crosshair');
242
- var pos = mouseAbs(e);
243
- Coords.setPressed(pos);
244
- Selection.update();
245
- Tracker.activateHandlers(selectDrag, doneSelect, e.type.substring(0,5)==='touch');
246
- KeyManager.watchKeys();
247
-
248
- e.stopPropagation();
249
- e.preventDefault();
250
- return false;
251
- }
252
- //}}}
253
- function selectDrag(pos) //{{{
254
- {
255
- Coords.setCurrent(pos);
256
- Selection.update();
257
- }
258
- //}}}
259
- function newTracker() //{{{
260
- {
261
- var trk = $('<div></div>').addClass(cssClass('tracker'));
262
- if (is_msie) {
263
- trk.css({
264
- opacity: 0,
265
- backgroundColor: 'white'
266
- });
267
- }
268
- return trk;
269
- }
270
- //}}}
271
-
272
- // }}}
273
- // Initialization {{{
274
- // Sanitize some options {{{
275
- if (typeof(obj) !== 'object') {
276
- obj = $(obj)[0];
277
- }
278
- if (typeof(opt) !== 'object') {
279
- opt = {};
280
- }
281
- // }}}
282
- setOptions(opt);
283
- // Initialize some jQuery objects {{{
284
- // The values are SET on the image(s) for the interface
285
- // If the original image has any of these set, they will be reset
286
- // However, if you destroy() the Jcrop instance the original image's
287
- // character in the DOM will be as you left it.
288
- var img_css = {
289
- border: 'none',
290
- visibility: 'visible',
291
- margin: 0,
292
- padding: 0,
293
- position: 'absolute',
294
- top: 0,
295
- left: 0
296
- };
297
-
298
- var $origimg = $(obj),
299
- img_mode = true;
300
-
301
- if (obj.tagName == 'IMG') {
302
- // Fix size of crop image.
303
- // Necessary when crop image is within a hidden element when page is loaded.
304
- if ($origimg[0].width != 0 && $origimg[0].height != 0) {
305
- // Obtain dimensions from contained img element.
306
- $origimg.width($origimg[0].width);
307
- $origimg.height($origimg[0].height);
308
- } else {
309
- // Obtain dimensions from temporary image in case the original is not loaded yet (e.g. IE 7.0).
310
- var tempImage = new Image();
311
- tempImage.src = $origimg[0].src;
312
- $origimg.width(tempImage.width);
313
- $origimg.height(tempImage.height);
314
- }
315
-
316
- var $img = $origimg.clone().removeAttr('id').css(img_css).show();
317
-
318
- $img.width($origimg.width());
319
- $img.height($origimg.height());
320
- $origimg.after($img).hide();
321
-
322
- } else {
323
- $img = $origimg.css(img_css).show();
324
- img_mode = false;
325
- if (options.shade === null) { options.shade = true; }
326
- }
327
-
328
- presize($img, options.boxWidth, options.boxHeight);
329
-
330
- var boundx = $img.width(),
331
- boundy = $img.height(),
332
-
333
-
334
- $div = $('<div />').width(boundx).height(boundy).addClass(cssClass('holder')).css({
335
- position: 'relative',
336
- backgroundColor: options.bgColor
337
- }).insertAfter($origimg).append($img);
338
-
339
- if (options.addClass) {
340
- $div.addClass(options.addClass);
341
- }
342
-
343
- var $img2 = $('<div />'),
344
-
345
- $img_holder = $('<div />')
346
- .width('100%').height('100%').css({
347
- zIndex: 310,
348
- position: 'absolute',
349
- overflow: 'hidden'
350
- }),
351
-
352
- $hdl_holder = $('<div />')
353
- .width('100%').height('100%').css('zIndex', 320),
354
-
355
- $sel = $('<div />')
356
- .css({
357
- position: 'absolute',
358
- zIndex: 600
359
- }).dblclick(function(){
360
- var c = Coords.getFixed();
361
- options.onDblClick.call(api,c);
362
- }).insertBefore($img).append($img_holder, $hdl_holder);
363
-
364
- if (img_mode) {
365
-
366
- $img2 = $('<img />')
367
- .attr('src', $img.attr('src')).css(img_css).width(boundx).height(boundy),
368
-
369
- $img_holder.append($img2);
370
-
371
- }
372
-
373
- if (ie6mode) {
374
- $sel.css({
375
- overflowY: 'hidden'
376
- });
377
- }
378
-
379
- var bound = options.boundary;
380
- var $trk = newTracker().width(boundx + (bound * 2)).height(boundy + (bound * 2)).css({
381
- position: 'absolute',
382
- top: px(-bound),
383
- left: px(-bound),
384
- zIndex: 290
385
- }).mousedown(newSelection);
386
-
387
- /* }}} */
388
- // Set more variables {{{
389
- var bgcolor = options.bgColor,
390
- bgopacity = options.bgOpacity,
391
- xlimit, ylimit, xmin, ymin, xscale, yscale, enabled = true,
392
- btndown, animating, shift_down;
393
-
394
- docOffset = getPos($img);
395
- // }}}
396
- // }}}
397
- // Internal Modules {{{
398
- // Touch Module {{{
399
- var Touch = (function () {
400
- // Touch support detection function adapted (under MIT License)
401
- // from code by Jeffrey Sambells - http://github.com/iamamused/
402
- function hasTouchSupport() {
403
- var support = {}, events = ['touchstart', 'touchmove', 'touchend'],
404
- el = document.createElement('div'), i;
405
-
406
- try {
407
- for(i=0; i<events.length; i++) {
408
- var eventName = events[i];
409
- eventName = 'on' + eventName;
410
- var isSupported = (eventName in el);
411
- if (!isSupported) {
412
- el.setAttribute(eventName, 'return;');
413
- isSupported = typeof el[eventName] == 'function';
414
- }
415
- support[events[i]] = isSupported;
416
- }
417
- return support.touchstart && support.touchend && support.touchmove;
418
- }
419
- catch(err) {
420
- return false;
421
- }
422
- }
423
-
424
- function detectSupport() {
425
- if ((options.touchSupport === true) || (options.touchSupport === false)) return options.touchSupport;
426
- else return hasTouchSupport();
427
- }
428
- return {
429
- createDragger: function (ord) {
430
- return function (e) {
431
- if (options.disabled) {
432
- return false;
433
- }
434
- if ((ord === 'move') && !options.allowMove) {
435
- return false;
436
- }
437
- docOffset = getPos($img);
438
- btndown = true;
439
- startDragMode(ord, mouseAbs(Touch.cfilter(e)), true);
440
- e.stopPropagation();
441
- e.preventDefault();
442
- return false;
443
- };
444
- },
445
- newSelection: function (e) {
446
- return newSelection(Touch.cfilter(e));
447
- },
448
- cfilter: function (e){
449
- e.pageX = e.originalEvent.changedTouches[0].pageX;
450
- e.pageY = e.originalEvent.changedTouches[0].pageY;
451
- return e;
452
- },
453
- isSupported: hasTouchSupport,
454
- support: detectSupport()
455
- };
456
- }());
457
- // }}}
458
- // Coords Module {{{
459
- var Coords = (function () {
460
- var x1 = 0,
461
- y1 = 0,
462
- x2 = 0,
463
- y2 = 0,
464
- ox, oy;
465
-
466
- function setPressed(pos) //{{{
467
- {
468
- pos = rebound(pos);
469
- x2 = x1 = pos[0];
470
- y2 = y1 = pos[1];
471
- }
472
- //}}}
473
- function setCurrent(pos) //{{{
474
- {
475
- pos = rebound(pos);
476
- ox = pos[0] - x2;
477
- oy = pos[1] - y2;
478
- x2 = pos[0];
479
- y2 = pos[1];
480
- }
481
- //}}}
482
- function getOffset() //{{{
483
- {
484
- return [ox, oy];
485
- }
486
- //}}}
487
- function moveOffset(offset) //{{{
488
- {
489
- var ox = offset[0],
490
- oy = offset[1];
491
-
492
- if (0 > x1 + ox) {
493
- ox -= ox + x1;
494
- }
495
- if (0 > y1 + oy) {
496
- oy -= oy + y1;
497
- }
498
-
499
- if (boundy < y2 + oy) {
500
- oy += boundy - (y2 + oy);
501
- }
502
- if (boundx < x2 + ox) {
503
- ox += boundx - (x2 + ox);
504
- }
505
-
506
- x1 += ox;
507
- x2 += ox;
508
- y1 += oy;
509
- y2 += oy;
510
- }
511
- //}}}
512
- function getCorner(ord) //{{{
513
- {
514
- var c = getFixed();
515
- switch (ord) {
516
- case 'ne':
517
- return [c.x2, c.y];
518
- case 'nw':
519
- return [c.x, c.y];
520
- case 'se':
521
- return [c.x2, c.y2];
522
- case 'sw':
523
- return [c.x, c.y2];
524
- }
525
- }
526
- //}}}
527
- function getFixed() //{{{
528
- {
529
- if (!options.aspectRatio) {
530
- return getRect();
531
- }
532
- // This function could use some optimization I think...
533
- var aspect = options.aspectRatio,
534
- min_x = options.minSize[0] / xscale,
535
-
536
-
537
- //min_y = options.minSize[1]/yscale,
538
- max_x = options.maxSize[0] / xscale,
539
- max_y = options.maxSize[1] / yscale,
540
- rw = x2 - x1,
541
- rh = y2 - y1,
542
- rwa = Math.abs(rw),
543
- rha = Math.abs(rh),
544
- real_ratio = rwa / rha,
545
- xx, yy, w, h;
546
-
547
- if (max_x === 0) {
548
- max_x = boundx * 10;
549
- }
550
- if (max_y === 0) {
551
- max_y = boundy * 10;
552
- }
553
- if (real_ratio < aspect) {
554
- yy = y2;
555
- w = rha * aspect;
556
- xx = rw < 0 ? x1 - w : w + x1;
557
-
558
- if (xx < 0) {
559
- xx = 0;
560
- h = Math.abs((xx - x1) / aspect);
561
- yy = rh < 0 ? y1 - h : h + y1;
562
- } else if (xx > boundx) {
563
- xx = boundx;
564
- h = Math.abs((xx - x1) / aspect);
565
- yy = rh < 0 ? y1 - h : h + y1;
566
- }
567
- } else {
568
- xx = x2;
569
- h = rwa / aspect;
570
- yy = rh < 0 ? y1 - h : y1 + h;
571
- if (yy < 0) {
572
- yy = 0;
573
- w = Math.abs((yy - y1) * aspect);
574
- xx = rw < 0 ? x1 - w : w + x1;
575
- } else if (yy > boundy) {
576
- yy = boundy;
577
- w = Math.abs(yy - y1) * aspect;
578
- xx = rw < 0 ? x1 - w : w + x1;
579
- }
580
- }
581
-
582
- // Magic %-)
583
- if (xx > x1) { // right side
584
- if (xx - x1 < min_x) {
585
- xx = x1 + min_x;
586
- } else if (xx - x1 > max_x) {
587
- xx = x1 + max_x;
588
- }
589
- if (yy > y1) {
590
- yy = y1 + (xx - x1) / aspect;
591
- } else {
592
- yy = y1 - (xx - x1) / aspect;
593
- }
594
- } else if (xx < x1) { // left side
595
- if (x1 - xx < min_x) {
596
- xx = x1 - min_x;
597
- } else if (x1 - xx > max_x) {
598
- xx = x1 - max_x;
599
- }
600
- if (yy > y1) {
601
- yy = y1 + (x1 - xx) / aspect;
602
- } else {
603
- yy = y1 - (x1 - xx) / aspect;
604
- }
605
- }
606
-
607
- if (xx < 0) {
608
- x1 -= xx;
609
- xx = 0;
610
- } else if (xx > boundx) {
611
- x1 -= xx - boundx;
612
- xx = boundx;
613
- }
614
-
615
- if (yy < 0) {
616
- y1 -= yy;
617
- yy = 0;
618
- } else if (yy > boundy) {
619
- y1 -= yy - boundy;
620
- yy = boundy;
621
- }
622
-
623
- return makeObj(flipCoords(x1, y1, xx, yy));
624
- }
625
- //}}}
626
- function rebound(p) //{{{
627
- {
628
- if (p[0] < 0) p[0] = 0;
629
- if (p[1] < 0) p[1] = 0;
630
-
631
- if (p[0] > boundx) p[0] = boundx;
632
- if (p[1] > boundy) p[1] = boundy;
633
-
634
- return [Math.round(p[0]), Math.round(p[1])];
635
- }
636
- //}}}
637
- function flipCoords(x1, y1, x2, y2) //{{{
638
- {
639
- var xa = x1,
640
- xb = x2,
641
- ya = y1,
642
- yb = y2;
643
- if (x2 < x1) {
644
- xa = x2;
645
- xb = x1;
646
- }
647
- if (y2 < y1) {
648
- ya = y2;
649
- yb = y1;
650
- }
651
- return [xa, ya, xb, yb];
652
- }
653
- //}}}
654
- function getRect() //{{{
655
- {
656
- var xsize = x2 - x1,
657
- ysize = y2 - y1,
658
- delta;
659
-
660
- if (xlimit && (Math.abs(xsize) > xlimit / xscale)) {
661
- x2 = (xsize > 0) ? (x1 + xlimit / xscale) : (x1 - xlimit / xscale);
662
- }
663
- if (ylimit && (Math.abs(ysize) > ylimit / yscale)) {
664
- y2 = (ysize > 0) ? (y1 + ylimit / yscale) : (y1 - ylimit / yscale);
665
- }
666
-
667
- if (ymin / yscale && (Math.abs(ysize) < ymin / yscale)) {
668
- y2 = (ysize > 0) ? (y1 + ymin / yscale) : (y1 - ymin / yscale);
669
- }
670
- if (xmin / xscale && (Math.abs(xsize) < xmin / xscale)) {
671
- x2 = (xsize > 0) ? (x1 + xmin / xscale) : (x1 - xmin / xscale);
672
- }
673
-
674
- if (x1 < 0) {
675
- x2 -= x1;
676
- x1 -= x1;
677
- }
678
- if (y1 < 0) {
679
- y2 -= y1;
680
- y1 -= y1;
681
- }
682
- if (x2 < 0) {
683
- x1 -= x2;
684
- x2 -= x2;
685
- }
686
- if (y2 < 0) {
687
- y1 -= y2;
688
- y2 -= y2;
689
- }
690
- if (x2 > boundx) {
691
- delta = x2 - boundx;
692
- x1 -= delta;
693
- x2 -= delta;
694
- }
695
- if (y2 > boundy) {
696
- delta = y2 - boundy;
697
- y1 -= delta;
698
- y2 -= delta;
699
- }
700
- if (x1 > boundx) {
701
- delta = x1 - boundy;
702
- y2 -= delta;
703
- y1 -= delta;
704
- }
705
- if (y1 > boundy) {
706
- delta = y1 - boundy;
707
- y2 -= delta;
708
- y1 -= delta;
709
- }
710
-
711
- return makeObj(flipCoords(x1, y1, x2, y2));
712
- }
713
- //}}}
714
- function makeObj(a) //{{{
715
- {
716
- return {
717
- x: a[0],
718
- y: a[1],
719
- x2: a[2],
720
- y2: a[3],
721
- w: a[2] - a[0],
722
- h: a[3] - a[1]
723
- };
724
- }
725
- //}}}
726
-
727
- return {
728
- flipCoords: flipCoords,
729
- setPressed: setPressed,
730
- setCurrent: setCurrent,
731
- getOffset: getOffset,
732
- moveOffset: moveOffset,
733
- getCorner: getCorner,
734
- getFixed: getFixed
735
- };
736
- }());
737
-
738
- //}}}
739
- // Shade Module {{{
740
- var Shade = (function() {
741
- var enabled = false,
742
- holder = $('<div />').css({
743
- position: 'absolute',
744
- zIndex: 240,
745
- opacity: 0
746
- }),
747
- shades = {
748
- top: createShade(),
749
- left: createShade().height(boundy),
750
- right: createShade().height(boundy),
751
- bottom: createShade()
752
- };
753
-
754
- function resizeShades(w,h) {
755
- shades.left.css({ height: px(h) });
756
- shades.right.css({ height: px(h) });
757
- }
758
- function updateAuto()
759
- {
760
- return updateShade(Coords.getFixed());
761
- }
762
- function updateShade(c)
763
- {
764
- shades.top.css({
765
- left: px(c.x),
766
- width: px(c.w),
767
- height: px(c.y)
768
- });
769
- shades.bottom.css({
770
- top: px(c.y2),
771
- left: px(c.x),
772
- width: px(c.w),
773
- height: px(boundy-c.y2)
774
- });
775
- shades.right.css({
776
- left: px(c.x2),
777
- width: px(boundx-c.x2)
778
- });
779
- shades.left.css({
780
- width: px(c.x)
781
- });
782
- }
783
- function createShade() {
784
- return $('<div />').css({
785
- position: 'absolute',
786
- backgroundColor: options.shadeColor||options.bgColor
787
- }).appendTo(holder);
788
- }
789
- function enableShade() {
790
- if (!enabled) {
791
- enabled = true;
792
- holder.insertBefore($img);
793
- updateAuto();
794
- Selection.setBgOpacity(1,0,1);
795
- $img2.hide();
796
-
797
- setBgColor(options.shadeColor||options.bgColor,1);
798
- if (Selection.isAwake())
799
- {
800
- setOpacity(options.bgOpacity,1);
801
- }
802
- else setOpacity(1,1);
803
- }
804
- }
805
- function setBgColor(color,now) {
806
- colorChangeMacro(getShades(),color,now);
807
- }
808
- function disableShade() {
809
- if (enabled) {
810
- holder.remove();
811
- $img2.show();
812
- enabled = false;
813
- if (Selection.isAwake()) {
814
- Selection.setBgOpacity(options.bgOpacity,1,1);
815
- } else {
816
- Selection.setBgOpacity(1,1,1);
817
- Selection.disableHandles();
818
- }
819
- colorChangeMacro($div,0,1);
820
- }
821
- }
822
- function setOpacity(opacity,now) {
823
- if (enabled) {
824
- if (options.bgFade && !now) {
825
- holder.animate({
826
- opacity: 1-opacity
827
- },{
828
- queue: false,
829
- duration: options.fadeTime
830
- });
831
- }
832
- else holder.css({opacity:1-opacity});
833
- }
834
- }
835
- function refreshAll() {
836
- options.shade ? enableShade() : disableShade();
837
- if (Selection.isAwake()) setOpacity(options.bgOpacity);
838
- }
839
- function getShades() {
840
- return holder.children();
841
- }
842
-
843
- return {
844
- update: updateAuto,
845
- updateRaw: updateShade,
846
- getShades: getShades,
847
- setBgColor: setBgColor,
848
- enable: enableShade,
849
- disable: disableShade,
850
- resize: resizeShades,
851
- refresh: refreshAll,
852
- opacity: setOpacity
853
- };
854
- }());
855
- // }}}
856
- // Selection Module {{{
857
- var Selection = (function () {
858
- var awake,
859
- hdep = 370,
860
- borders = {},
861
- handle = {},
862
- dragbar = {},
863
- seehandles = false;
864
-
865
- // Private Methods
866
- function insertBorder(type) //{{{
867
- {
868
- var jq = $('<div />').css({
869
- position: 'absolute',
870
- opacity: options.borderOpacity
871
- }).addClass(cssClass(type));
872
- $img_holder.append(jq);
873
- return jq;
874
- }
875
- //}}}
876
- function dragDiv(ord, zi) //{{{
877
- {
878
- var jq = $('<div />').mousedown(createDragger(ord)).css({
879
- cursor: ord + '-resize',
880
- position: 'absolute',
881
- zIndex: zi
882
- }).addClass('ord-'+ord);
883
-
884
- if (Touch.support) {
885
- jq.bind('touchstart.jcrop', Touch.createDragger(ord));
886
- }
887
-
888
- $hdl_holder.append(jq);
889
- return jq;
890
- }
891
- //}}}
892
- function insertHandle(ord) //{{{
893
- {
894
- var hs = options.handleSize,
895
-
896
- div = dragDiv(ord, hdep++).css({
897
- opacity: options.handleOpacity
898
- }).addClass(cssClass('handle'));
899
-
900
- if (hs) { div.width(hs).height(hs); }
901
-
902
- return div;
903
- }
904
- //}}}
905
- function insertDragbar(ord) //{{{
906
- {
907
- return dragDiv(ord, hdep++).addClass('jcrop-dragbar');
908
- }
909
- //}}}
910
- function createDragbars(li) //{{{
911
- {
912
- var i;
913
- for (i = 0; i < li.length; i++) {
914
- dragbar[li[i]] = insertDragbar(li[i]);
915
- }
916
- }
917
- //}}}
918
- function createBorders(li) //{{{
919
- {
920
- var cl,i;
921
- for (i = 0; i < li.length; i++) {
922
- switch(li[i]){
923
- case'n': cl='hline'; break;
924
- case's': cl='hline bottom'; break;
925
- case'e': cl='vline right'; break;
926
- case'w': cl='vline'; break;
927
- }
928
- borders[li[i]] = insertBorder(cl);
929
- }
930
- }
931
- //}}}
932
- function createHandles(li) //{{{
933
- {
934
- var i;
935
- for (i = 0; i < li.length; i++) {
936
- handle[li[i]] = insertHandle(li[i]);
937
- }
938
- }
939
- //}}}
940
- function moveto(x, y) //{{{
941
- {
942
- if (!options.shade) {
943
- $img2.css({
944
- top: px(-y),
945
- left: px(-x)
946
- });
947
- }
948
- $sel.css({
949
- top: px(y),
950
- left: px(x)
951
- });
952
- }
953
- //}}}
954
- function resize(w, h) //{{{
955
- {
956
- $sel.width(Math.round(w)).height(Math.round(h));
957
- }
958
- //}}}
959
- function refresh() //{{{
960
- {
961
- var c = Coords.getFixed();
962
-
963
- Coords.setPressed([c.x, c.y]);
964
- Coords.setCurrent([c.x2, c.y2]);
965
-
966
- updateVisible();
967
- }
968
- //}}}
969
-
970
- // Internal Methods
971
- function updateVisible(select) //{{{
972
- {
973
- if (awake) {
974
- return update(select);
975
- }
976
- }
977
- //}}}
978
- function update(select) //{{{
979
- {
980
- var c = Coords.getFixed();
981
-
982
- resize(c.w, c.h);
983
- moveto(c.x, c.y);
984
- if (options.shade) Shade.updateRaw(c);
985
-
986
- awake || show();
987
-
988
- if (select) {
989
- options.onSelect.call(api, unscale(c));
990
- } else {
991
- options.onChange.call(api, unscale(c));
992
- }
993
- }
994
- //}}}
995
- function setBgOpacity(opacity,force,now) //{{{
996
- {
997
- if (!awake && !force) return;
998
- if (options.bgFade && !now) {
999
- $img.animate({
1000
- opacity: opacity
1001
- },{
1002
- queue: false,
1003
- duration: options.fadeTime
1004
- });
1005
- } else {
1006
- $img.css('opacity', opacity);
1007
- }
1008
- }
1009
- //}}}
1010
- function show() //{{{
1011
- {
1012
- $sel.show();
1013
-
1014
- if (options.shade) Shade.opacity(bgopacity);
1015
- else setBgOpacity(bgopacity,true);
1016
-
1017
- awake = true;
1018
- }
1019
- //}}}
1020
- function release() //{{{
1021
- {
1022
- disableHandles();
1023
- $sel.hide();
1024
-
1025
- if (options.shade) Shade.opacity(1);
1026
- else setBgOpacity(1);
1027
-
1028
- awake = false;
1029
- options.onRelease.call(api);
1030
- }
1031
- //}}}
1032
- function showHandles() //{{{
1033
- {
1034
- if (seehandles) {
1035
- $hdl_holder.show();
1036
- }
1037
- }
1038
- //}}}
1039
- function enableHandles() //{{{
1040
- {
1041
- seehandles = true;
1042
- if (options.allowResize) {
1043
- $hdl_holder.show();
1044
- return true;
1045
- }
1046
- }
1047
- //}}}
1048
- function disableHandles() //{{{
1049
- {
1050
- seehandles = false;
1051
- $hdl_holder.hide();
1052
- }
1053
- //}}}
1054
- function animMode(v) //{{{
1055
- {
1056
- if (v) {
1057
- animating = true;
1058
- disableHandles();
1059
- } else {
1060
- animating = false;
1061
- enableHandles();
1062
- }
1063
- }
1064
- //}}}
1065
- function done() //{{{
1066
- {
1067
- animMode(false);
1068
- refresh();
1069
- }
1070
- //}}}
1071
- // Insert draggable elements {{{
1072
- // Insert border divs for outline
1073
-
1074
- if (options.dragEdges && $.isArray(options.createDragbars))
1075
- createDragbars(options.createDragbars);
1076
-
1077
- if ($.isArray(options.createHandles))
1078
- createHandles(options.createHandles);
1079
-
1080
- if (options.drawBorders && $.isArray(options.createBorders))
1081
- createBorders(options.createBorders);
1082
-
1083
- //}}}
1084
-
1085
- // This is a hack for iOS5 to support drag/move touch functionality
1086
- $(document).bind('touchstart.jcrop-ios',function(e) {
1087
- if ($(e.currentTarget).hasClass('jcrop-tracker')) e.stopPropagation();
1088
- });
1089
-
1090
- var $track = newTracker().mousedown(createDragger('move')).css({
1091
- cursor: 'move',
1092
- position: 'absolute',
1093
- zIndex: 360
1094
- });
1095
-
1096
- if (Touch.support) {
1097
- $track.bind('touchstart.jcrop', Touch.createDragger('move'));
1098
- }
1099
-
1100
- $img_holder.append($track);
1101
- disableHandles();
1102
-
1103
- return {
1104
- updateVisible: updateVisible,
1105
- update: update,
1106
- release: release,
1107
- refresh: refresh,
1108
- isAwake: function () {
1109
- return awake;
1110
- },
1111
- setCursor: function (cursor) {
1112
- $track.css('cursor', cursor);
1113
- },
1114
- enableHandles: enableHandles,
1115
- enableOnly: function () {
1116
- seehandles = true;
1117
- },
1118
- showHandles: showHandles,
1119
- disableHandles: disableHandles,
1120
- animMode: animMode,
1121
- setBgOpacity: setBgOpacity,
1122
- done: done
1123
- };
1124
- }());
1125
-
1126
- //}}}
1127
- // Tracker Module {{{
1128
- var Tracker = (function () {
1129
- var onMove = function () {},
1130
- onDone = function () {},
1131
- trackDoc = options.trackDocument;
1132
-
1133
- function toFront(touch) //{{{
1134
- {
1135
- $trk.css({
1136
- zIndex: 450
1137
- });
1138
-
1139
- if (touch)
1140
- $(document)
1141
- .bind('touchmove.jcrop', trackTouchMove)
1142
- .bind('touchend.jcrop', trackTouchEnd);
1143
-
1144
- else if (trackDoc)
1145
- $(document)
1146
- .bind('mousemove.jcrop',trackMove)
1147
- .bind('mouseup.jcrop',trackUp);
1148
- }
1149
- //}}}
1150
- function toBack() //{{{
1151
- {
1152
- $trk.css({
1153
- zIndex: 290
1154
- });
1155
- $(document).unbind('.jcrop');
1156
- }
1157
- //}}}
1158
- function trackMove(e) //{{{
1159
- {
1160
- onMove(mouseAbs(e));
1161
- return false;
1162
- }
1163
- //}}}
1164
- function trackUp(e) //{{{
1165
- {
1166
- e.preventDefault();
1167
- e.stopPropagation();
1168
-
1169
- if (btndown) {
1170
- btndown = false;
1171
-
1172
- onDone(mouseAbs(e));
1173
-
1174
- if (Selection.isAwake()) {
1175
- options.onSelect.call(api, unscale(Coords.getFixed()));
1176
- }
1177
-
1178
- toBack();
1179
- onMove = function () {};
1180
- onDone = function () {};
1181
- }
1182
-
1183
- return false;
1184
- }
1185
- //}}}
1186
- function activateHandlers(move, done, touch) //{{{
1187
- {
1188
- btndown = true;
1189
- onMove = move;
1190
- onDone = done;
1191
- toFront(touch);
1192
- return false;
1193
- }
1194
- //}}}
1195
- function trackTouchMove(e) //{{{
1196
- {
1197
- onMove(mouseAbs(Touch.cfilter(e)));
1198
- return false;
1199
- }
1200
- //}}}
1201
- function trackTouchEnd(e) //{{{
1202
- {
1203
- return trackUp(Touch.cfilter(e));
1204
- }
1205
- //}}}
1206
- function setCursor(t) //{{{
1207
- {
1208
- $trk.css('cursor', t);
1209
- }
1210
- //}}}
1211
-
1212
- if (!trackDoc) {
1213
- $trk.mousemove(trackMove).mouseup(trackUp).mouseout(trackUp);
1214
- }
1215
-
1216
- $img.before($trk);
1217
- return {
1218
- activateHandlers: activateHandlers,
1219
- setCursor: setCursor
1220
- };
1221
- }());
1222
- //}}}
1223
- // KeyManager Module {{{
1224
- var KeyManager = (function () {
1225
- var $keymgr = $('<input type="radio" />').css({
1226
- position: 'fixed',
1227
- left: '-120px',
1228
- width: '12px'
1229
- }).addClass('jcrop-keymgr'),
1230
-
1231
- $keywrap = $('<div />').css({
1232
- position: 'absolute',
1233
- overflow: 'hidden'
1234
- }).append($keymgr);
1235
-
1236
- function watchKeys() //{{{
1237
- {
1238
- if (options.keySupport) {
1239
- $keymgr.show();
1240
- $keymgr.focus();
1241
- }
1242
- }
1243
- //}}}
1244
- function onBlur(e) //{{{
1245
- {
1246
- $keymgr.hide();
1247
- }
1248
- //}}}
1249
- function doNudge(e, x, y) //{{{
1250
- {
1251
- if (options.allowMove) {
1252
- Coords.moveOffset([x, y]);
1253
- Selection.updateVisible(true);
1254
- }
1255
- e.preventDefault();
1256
- e.stopPropagation();
1257
- }
1258
- //}}}
1259
- function parseKey(e) //{{{
1260
- {
1261
- if (e.ctrlKey || e.metaKey) {
1262
- return true;
1263
- }
1264
- shift_down = e.shiftKey ? true : false;
1265
- var nudge = shift_down ? 10 : 1;
1266
-
1267
- switch (e.keyCode) {
1268
- case 37:
1269
- doNudge(e, -nudge, 0);
1270
- break;
1271
- case 39:
1272
- doNudge(e, nudge, 0);
1273
- break;
1274
- case 38:
1275
- doNudge(e, 0, -nudge);
1276
- break;
1277
- case 40:
1278
- doNudge(e, 0, nudge);
1279
- break;
1280
- case 27:
1281
- if (options.allowSelect) Selection.release();
1282
- break;
1283
- case 9:
1284
- return true;
1285
- }
1286
-
1287
- return false;
1288
- }
1289
- //}}}
1290
-
1291
- if (options.keySupport) {
1292
- $keymgr.keydown(parseKey).blur(onBlur);
1293
- if (ie6mode || !options.fixedSupport) {
1294
- $keymgr.css({
1295
- position: 'absolute',
1296
- left: '-20px'
1297
- });
1298
- $keywrap.append($keymgr).insertBefore($img);
1299
- } else {
1300
- $keymgr.insertBefore($img);
1301
- }
1302
- }
1303
-
1304
-
1305
- return {
1306
- watchKeys: watchKeys
1307
- };
1308
- }());
1309
- //}}}
1310
- // }}}
1311
- // API methods {{{
1312
- function setClass(cname) //{{{
1313
- {
1314
- $div.removeClass().addClass(cssClass('holder')).addClass(cname);
1315
- }
1316
- //}}}
1317
- function animateTo(a, callback) //{{{
1318
- {
1319
- var x1 = a[0] / xscale,
1320
- y1 = a[1] / yscale,
1321
- x2 = a[2] / xscale,
1322
- y2 = a[3] / yscale;
1323
-
1324
- if (animating) {
1325
- return;
1326
- }
1327
-
1328
- var animto = Coords.flipCoords(x1, y1, x2, y2),
1329
- c = Coords.getFixed(),
1330
- initcr = [c.x, c.y, c.x2, c.y2],
1331
- animat = initcr,
1332
- interv = options.animationDelay,
1333
- ix1 = animto[0] - initcr[0],
1334
- iy1 = animto[1] - initcr[1],
1335
- ix2 = animto[2] - initcr[2],
1336
- iy2 = animto[3] - initcr[3],
1337
- pcent = 0,
1338
- velocity = options.swingSpeed;
1339
-
1340
- x1 = animat[0];
1341
- y1 = animat[1];
1342
- x2 = animat[2];
1343
- y2 = animat[3];
1344
-
1345
- Selection.animMode(true);
1346
- var anim_timer;
1347
-
1348
- function queueAnimator() {
1349
- window.setTimeout(animator, interv);
1350
- }
1351
- var animator = (function () {
1352
- return function () {
1353
- pcent += (100 - pcent) / velocity;
1354
-
1355
- animat[0] = Math.round(x1 + ((pcent / 100) * ix1));
1356
- animat[1] = Math.round(y1 + ((pcent / 100) * iy1));
1357
- animat[2] = Math.round(x2 + ((pcent / 100) * ix2));
1358
- animat[3] = Math.round(y2 + ((pcent / 100) * iy2));
1359
-
1360
- if (pcent >= 99.8) {
1361
- pcent = 100;
1362
- }
1363
- if (pcent < 100) {
1364
- setSelectRaw(animat);
1365
- queueAnimator();
1366
- } else {
1367
- Selection.done();
1368
- Selection.animMode(false);
1369
- if (typeof(callback) === 'function') {
1370
- callback.call(api);
1371
- }
1372
- }
1373
- };
1374
- }());
1375
- queueAnimator();
1376
- }
1377
- //}}}
1378
- function setSelect(rect) //{{{
1379
- {
1380
- setSelectRaw([rect[0] / xscale, rect[1] / yscale, rect[2] / xscale, rect[3] / yscale]);
1381
- options.onSelect.call(api, unscale(Coords.getFixed()));
1382
- Selection.enableHandles();
1383
- }
1384
- //}}}
1385
- function setSelectRaw(l) //{{{
1386
- {
1387
- Coords.setPressed([l[0], l[1]]);
1388
- Coords.setCurrent([l[2], l[3]]);
1389
- Selection.update();
1390
- }
1391
- //}}}
1392
- function tellSelect() //{{{
1393
- {
1394
- return unscale(Coords.getFixed());
1395
- }
1396
- //}}}
1397
- function tellScaled() //{{{
1398
- {
1399
- return Coords.getFixed();
1400
- }
1401
- //}}}
1402
- function setOptionsNew(opt) //{{{
1403
- {
1404
- setOptions(opt);
1405
- interfaceUpdate();
1406
- }
1407
- //}}}
1408
- function disableCrop() //{{{
1409
- {
1410
- options.disabled = true;
1411
- Selection.disableHandles();
1412
- Selection.setCursor('default');
1413
- Tracker.setCursor('default');
1414
- }
1415
- //}}}
1416
- function enableCrop() //{{{
1417
- {
1418
- options.disabled = false;
1419
- interfaceUpdate();
1420
- }
1421
- //}}}
1422
- function cancelCrop() //{{{
1423
- {
1424
- Selection.done();
1425
- Tracker.activateHandlers(null, null);
1426
- }
1427
- //}}}
1428
- function destroy() //{{{
1429
- {
1430
- $div.remove();
1431
- $origimg.show();
1432
- $origimg.css('visibility','visible');
1433
- $(obj).removeData('Jcrop');
1434
- }
1435
- //}}}
1436
- function setImage(src, callback) //{{{
1437
- {
1438
- Selection.release();
1439
- disableCrop();
1440
- var img = new Image();
1441
- img.onload = function () {
1442
- var iw = img.width;
1443
- var ih = img.height;
1444
- var bw = options.boxWidth;
1445
- var bh = options.boxHeight;
1446
- $img.width(iw).height(ih);
1447
- $img.attr('src', src);
1448
- $img2.attr('src', src);
1449
- presize($img, bw, bh);
1450
- boundx = $img.width();
1451
- boundy = $img.height();
1452
- $img2.width(boundx).height(boundy);
1453
- $trk.width(boundx + (bound * 2)).height(boundy + (bound * 2));
1454
- $div.width(boundx).height(boundy);
1455
- Shade.resize(boundx,boundy);
1456
- enableCrop();
1457
-
1458
- if (typeof(callback) === 'function') {
1459
- callback.call(api);
1460
- }
1461
- };
1462
- img.src = src;
1463
- }
1464
- //}}}
1465
- function colorChangeMacro($obj,color,now) {
1466
- var mycolor = color || options.bgColor;
1467
- if (options.bgFade && supportsColorFade() && options.fadeTime && !now) {
1468
- $obj.animate({
1469
- backgroundColor: mycolor
1470
- }, {
1471
- queue: false,
1472
- duration: options.fadeTime
1473
- });
1474
- } else {
1475
- $obj.css('backgroundColor', mycolor);
1476
- }
1477
- }
1478
- function interfaceUpdate(alt) //{{{
1479
- // This method tweaks the interface based on options object.
1480
- // Called when options are changed and at end of initialization.
1481
- {
1482
- if (options.allowResize) {
1483
- if (alt) {
1484
- Selection.enableOnly();
1485
- } else {
1486
- Selection.enableHandles();
1487
- }
1488
- } else {
1489
- Selection.disableHandles();
1490
- }
1491
-
1492
- Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default');
1493
- Selection.setCursor(options.allowMove ? 'move' : 'default');
1494
-
1495
- if (options.hasOwnProperty('trueSize')) {
1496
- xscale = options.trueSize[0] / boundx;
1497
- yscale = options.trueSize[1] / boundy;
1498
- }
1499
-
1500
- if (options.hasOwnProperty('setSelect')) {
1501
- setSelect(options.setSelect);
1502
- Selection.done();
1503
- delete(options.setSelect);
1504
- }
1505
-
1506
- Shade.refresh();
1507
-
1508
- if (options.bgColor != bgcolor) {
1509
- colorChangeMacro(
1510
- options.shade? Shade.getShades(): $div,
1511
- options.shade?
1512
- (options.shadeColor || options.bgColor):
1513
- options.bgColor
1514
- );
1515
- bgcolor = options.bgColor;
1516
- }
1517
-
1518
- if (bgopacity != options.bgOpacity) {
1519
- bgopacity = options.bgOpacity;
1520
- if (options.shade) Shade.refresh();
1521
- else Selection.setBgOpacity(bgopacity);
1522
- }
1523
-
1524
- xlimit = options.maxSize[0] || 0;
1525
- ylimit = options.maxSize[1] || 0;
1526
- xmin = options.minSize[0] || 0;
1527
- ymin = options.minSize[1] || 0;
1528
-
1529
- if (options.hasOwnProperty('outerImage')) {
1530
- $img.attr('src', options.outerImage);
1531
- delete(options.outerImage);
1532
- }
1533
-
1534
- Selection.refresh();
1535
- }
1536
- //}}}
1537
- //}}}
1538
-
1539
- if (Touch.support) $trk.bind('touchstart.jcrop', Touch.newSelection);
1540
-
1541
- $hdl_holder.hide();
1542
- interfaceUpdate(true);
1543
-
1544
- var api = {
1545
- setImage: setImage,
1546
- animateTo: animateTo,
1547
- setSelect: setSelect,
1548
- setOptions: setOptionsNew,
1549
- tellSelect: tellSelect,
1550
- tellScaled: tellScaled,
1551
- setClass: setClass,
1552
-
1553
- disable: disableCrop,
1554
- enable: enableCrop,
1555
- cancel: cancelCrop,
1556
- release: Selection.release,
1557
- destroy: destroy,
1558
-
1559
- focus: KeyManager.watchKeys,
1560
-
1561
- getBounds: function () {
1562
- return [boundx * xscale, boundy * yscale];
1563
- },
1564
- getWidgetSize: function () {
1565
- return [boundx, boundy];
1566
- },
1567
- getScaleFactor: function () {
1568
- return [xscale, yscale];
1569
- },
1570
- getOptions: function() {
1571
- // careful: internal values are returned
1572
- return options;
1573
- },
1574
-
1575
- ui: {
1576
- holder: $div,
1577
- selection: $sel
1578
- }
1579
- };
1580
-
1581
- if (is_msie) $div.bind('selectstart', function () { return false; });
1582
-
1583
- $origimg.data('Jcrop', api);
1584
- return api;
1585
- };
1586
- $.fn.Jcrop = function (options, callback) //{{{
1587
- {
1588
- var api;
1589
- // Iterate over each object, attach Jcrop
1590
- this.each(function () {
1591
- // If we've already attached to this object
1592
- if ($(this).data('Jcrop')) {
1593
- // The API can be requested this way (undocumented)
1594
- if (options === 'api') return $(this).data('Jcrop');
1595
- // Otherwise, we just reset the options...
1596
- else $(this).data('Jcrop').setOptions(options);
1597
- }
1598
- // If we haven't been attached, preload and attach
1599
- else {
1600
- if (this.tagName == 'IMG')
1601
- $.Jcrop.Loader(this,function(){
1602
- $(this).css({display:'block',visibility:'hidden'});
1603
- api = $.Jcrop(this, options);
1604
- if ($.isFunction(callback)) callback.call(api);
1605
- });
1606
- else {
1607
- $(this).css({display:'block',visibility:'hidden'});
1608
- api = $.Jcrop(this, options);
1609
- if ($.isFunction(callback)) callback.call(api);
1610
- }
1611
- }
1612
- });
1613
-
1614
- // Return "this" so the object is chainable (jQuery-style)
1615
- return this;
1616
- };
1617
- //}}}
1618
- // $.Jcrop.Loader - basic image loader {{{
1619
-
1620
- $.Jcrop.Loader = function(imgobj,success,error){
1621
- var $img = $(imgobj), img = $img[0];
1622
-
1623
- function completeCheck(){
1624
- if (img.complete) {
1625
- $img.unbind('.jcloader');
1626
- if ($.isFunction(success)) success.call(img);
1627
- }
1628
- else window.setTimeout(completeCheck,50);
1629
- }
1630
-
1631
- $img
1632
- .bind('load.jcloader',completeCheck)
1633
- .bind('error.jcloader',function(e){
1634
- $img.unbind('.jcloader');
1635
- if ($.isFunction(error)) error.call(img);
1636
- });
1637
-
1638
- if (img.complete && $.isFunction(success)){
1639
- $img.unbind('.jcloader');
1640
- success.call(img);
1641
- }
1642
- };
1643
-
1644
- //}}}
1645
- // Global Defaults {{{
1646
- $.Jcrop.defaults = {
1647
-
1648
- // Basic Settings
1649
- allowSelect: true,
1650
- allowMove: true,
1651
- allowResize: true,
1652
-
1653
- trackDocument: true,
1654
-
1655
- // Styling Options
1656
- baseClass: 'jcrop',
1657
- addClass: null,
1658
- bgColor: 'black',
1659
- bgOpacity: 0.6,
1660
- bgFade: false,
1661
- borderOpacity: 0.4,
1662
- handleOpacity: 0.5,
1663
- handleSize: null,
1664
-
1665
- aspectRatio: 0,
1666
- keySupport: true,
1667
- createHandles: ['n','s','e','w','nw','ne','se','sw'],
1668
- createDragbars: ['n','s','e','w'],
1669
- createBorders: ['n','s','e','w'],
1670
- drawBorders: true,
1671
- dragEdges: true,
1672
- fixedSupport: true,
1673
- touchSupport: null,
1674
-
1675
- shade: null,
1676
-
1677
- boxWidth: 0,
1678
- boxHeight: 0,
1679
- boundary: 2,
1680
- fadeTime: 400,
1681
- animationDelay: 20,
1682
- swingSpeed: 3,
1683
-
1684
- minSelect: [0, 0],
1685
- maxSize: [0, 0],
1686
- minSize: [0, 0],
1687
-
1688
- // Callbacks / Event Handlers
1689
- onChange: function () {},
1690
- onSelect: function () {},
1691
- onDblClick: function () {},
1692
- onRelease: function () {}
1693
- };
1694
-
1695
- // }}}
1696
- }(jQuery));