locomotive-aloha-rails 0.20.1.2 → 0.20.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. data/Rakefile +1 -1
  2. data/lib/aloha/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/aloha/css/aloha.css +3 -0
  4. data/vendor/assets/javascripts/aloha/css/ext-aloha.css +3 -0
  5. data/vendor/assets/javascripts/aloha/lib/aloha-bootstrap.js +4565 -3934
  6. data/vendor/assets/javascripts/aloha/lib/aloha.js +1357 -702
  7. data/vendor/assets/javascripts/aloha/lib/aloha/command.js +16 -13
  8. data/vendor/assets/javascripts/aloha/lib/aloha/core.js +23 -3
  9. data/vendor/assets/javascripts/aloha/lib/aloha/ecma5shims.js +23 -7
  10. data/vendor/assets/javascripts/aloha/lib/aloha/editable.js +57 -14
  11. data/vendor/assets/javascripts/aloha/lib/aloha/engine.js +9 -5
  12. data/vendor/assets/javascripts/aloha/lib/aloha/floatingmenu.js +288 -96
  13. data/vendor/assets/javascripts/aloha/lib/aloha/jquery.js +11 -1
  14. data/vendor/assets/javascripts/aloha/lib/aloha/markup.js +318 -40
  15. data/vendor/assets/javascripts/aloha/lib/aloha/repositorymanager.js +11 -10
  16. data/vendor/assets/javascripts/aloha/lib/aloha/selection.js +20 -1
  17. data/vendor/assets/javascripts/aloha/lib/aloha/sidebar.js +11 -1
  18. data/vendor/assets/javascripts/aloha/lib/jquery-plugin.js +10 -7
  19. data/vendor/assets/javascripts/aloha/lib/util/dom.js +18 -6
  20. data/vendor/assets/javascripts/aloha/lib/util/range.js +6 -6
  21. data/vendor/assets/javascripts/aloha/lib/vendor/ext-3.2.1/ext-all-debug.js +26 -2
  22. data/vendor/assets/javascripts/aloha/lib/vendor/jquery.store.js +39 -15
  23. data/vendor/assets/javascripts/aloha/plugins/common/abbr/lib/abbr-plugin.js +1 -0
  24. data/vendor/assets/javascripts/aloha/plugins/common/align/lib/align-plugin.js +344 -334
  25. data/vendor/assets/javascripts/aloha/plugins/common/block/css/block.css +65 -12
  26. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/block-plugin.js +12 -15
  27. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/block.js +796 -180
  28. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/blockcontenthandler.js +54 -13
  29. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/blockmanager.js +315 -78
  30. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/editor.js +111 -8
  31. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/editormanager.js +2 -0
  32. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/jquery-ui-1.8.16.custom.min.js +198 -0
  33. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/sidebarattributeeditor.js +7 -20
  34. data/vendor/assets/javascripts/aloha/plugins/common/characterpicker/lib/characterpicker-plugin.js +15 -3
  35. data/vendor/assets/javascripts/aloha/plugins/common/contenthandler/lib/sanitizecontenthandler.js +3 -2
  36. data/vendor/assets/javascripts/aloha/plugins/common/contenthandler/lib/wordcontenthandler.js +111 -5
  37. data/vendor/assets/javascripts/aloha/plugins/common/dom-to-xhtml/lib/dom-to-xhtml-plugin.js +29 -0
  38. data/vendor/assets/javascripts/aloha/plugins/common/dom-to-xhtml/lib/dom-to-xhtml.js +306 -0
  39. data/vendor/assets/javascripts/aloha/plugins/common/format/lib/format-plugin.js +59 -5
  40. data/vendor/assets/javascripts/aloha/plugins/common/format/nls/i18n.js +1 -1
  41. data/vendor/assets/javascripts/aloha/plugins/common/horizontalruler/lib/horizontalruler-plugin.js +18 -3
  42. data/vendor/assets/javascripts/aloha/plugins/common/image/img/crop-buttons.gif +0 -0
  43. data/vendor/assets/javascripts/aloha/plugins/common/image/lib/image-plugin.js +1629 -1601
  44. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/jcrop/jquery.jcrop.css +11 -0
  45. data/vendor/assets/javascripts/aloha/plugins/common/link/extra/linklist.js +8 -6
  46. data/vendor/assets/javascripts/aloha/plugins/common/link/lib/link-plugin.js +26 -10
  47. data/vendor/assets/javascripts/aloha/plugins/common/list/nls/de/i18n.js +5 -1
  48. data/vendor/assets/javascripts/aloha/plugins/common/paste/lib/paste-plugin.js +3 -4
  49. data/vendor/assets/javascripts/aloha/plugins/common/table/lib/table-cell.js +13 -12
  50. data/vendor/assets/javascripts/aloha/plugins/common/table/lib/table-plugin.js +108 -61
  51. data/vendor/assets/javascripts/aloha/plugins/common/table/lib/table-selection.js +61 -1
  52. data/vendor/assets/javascripts/aloha/plugins/common/table/lib/table.js +1 -0
  53. data/vendor/assets/javascripts/aloha/plugins/common/table/nls/de/i18n.js +28 -1
  54. data/vendor/assets/javascripts/aloha/plugins/common/table/nls/i18n.js +36 -10
  55. data/vendor/assets/javascripts/aloha/plugins/extra/browser/css/browser.jqgrid.css +292 -292
  56. data/vendor/assets/javascripts/aloha/plugins/extra/browser/lib/browser.js +28 -5
  57. data/vendor/assets/javascripts/aloha/plugins/extra/browser/lib/locale.js +2 -2
  58. data/vendor/assets/javascripts/aloha/plugins/extra/browser/vendor/grid.locale.de.js +6 -1
  59. data/vendor/assets/javascripts/aloha/plugins/extra/browser/vendor/grid.locale.en.js +5 -0
  60. data/vendor/assets/javascripts/aloha/plugins/extra/browser/vendor/jquery.jqGrid.js +5 -0
  61. data/vendor/assets/javascripts/aloha/plugins/extra/browser/vendor/jquery.jstree.js +6 -1
  62. data/vendor/assets/javascripts/aloha/plugins/extra/browser/vendor/jquery.ui.js +6 -1
  63. data/vendor/assets/javascripts/aloha/plugins/extra/browser/vendor/ui-layout.js +6 -1
  64. data/vendor/assets/javascripts/aloha/plugins/extra/cite/lib/cite-plugin.js +18 -4
  65. data/vendor/assets/javascripts/aloha/plugins/extra/formatlesspaste/lib/formatlesspaste-plugin.js +1 -1
  66. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/lib/linkbrowser-plugin.js +14 -2
  67. data/vendor/assets/javascripts/aloha/plugins/extra/numerated-headers/demo/js/aloha-config.js +2 -2
  68. data/vendor/assets/javascripts/aloha/plugins/extra/toc/lib/toc-plugin.js +382 -0
  69. data/vendor/assets/javascripts/aloha/plugins/extra/toc/nls/de/i18n.js +3 -0
  70. data/vendor/assets/javascripts/aloha/plugins/extra/toc/nls/i18n.js +4 -0
  71. metadata +15 -11
  72. data/vendor/assets/javascripts/aloha/plugins/extra/toc/i18n/de.json +0 -1
  73. data/vendor/assets/javascripts/aloha/plugins/extra/toc/i18n/en.json +0 -1
  74. data/vendor/assets/javascripts/aloha/plugins/extra/toc/src/toc.js +0 -350
@@ -25,7 +25,7 @@ function(Aloha, Plugin, jQuery, FloatingMenu, i18n, i18nCore) {
25
25
  /**
26
26
  * default button configuration
27
27
  */
28
- config: [ 'strong', 'em', 'b', 'i','del','sub','sup', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'pre', 'removeFormat'],
28
+ config: [ 'strong', 'em', 'b', 'i','s','sub','sup', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'pre', 'removeFormat'],
29
29
 
30
30
  /**
31
31
  * Initialize the plugin and set initialize flag on true
@@ -38,7 +38,6 @@ function(Aloha, Plugin, jQuery, FloatingMenu, i18n, i18nCore) {
38
38
 
39
39
  // apply specific configuration if an editable has been activated
40
40
  Aloha.bind('aloha-editable-activated',function (e, params) {
41
- //debugger;
42
41
  me.applyButtonConfig(params.editable.obj);
43
42
  });
44
43
 
@@ -60,7 +59,6 @@ function(Aloha, Plugin, jQuery, FloatingMenu, i18n, i18nCore) {
60
59
 
61
60
  var config = this.getEditableConfig(obj),
62
61
  button, i, len;
63
-
64
62
  // now iterate all buttons and show/hide them according to the config
65
63
  for ( button in this.buttons) {
66
64
  if (jQuery.inArray(button, config) != -1) {
@@ -102,6 +100,7 @@ function(Aloha, Plugin, jQuery, FloatingMenu, i18n, i18nCore) {
102
100
  jQuery.each(this.config, function(j, button) {
103
101
  switch( button ) {
104
102
  // text level semantics:
103
+ case 'u':
105
104
  case 'em':
106
105
  case 'strong':
107
106
  case 'b':
@@ -111,6 +110,7 @@ function(Aloha, Plugin, jQuery, FloatingMenu, i18n, i18nCore) {
111
110
  case 'code':
112
111
  case 'abbr':
113
112
  case 'del':
113
+ case 's':
114
114
  case 'sub':
115
115
  case 'sup':
116
116
  that.buttons[button] = {'button' : new Aloha.ui.Button({
@@ -121,14 +121,41 @@ function(Aloha, Plugin, jQuery, FloatingMenu, i18n, i18nCore) {
121
121
  var
122
122
  markup = jQuery('<'+button+'></'+button+'>'),
123
123
  rangeObject = Aloha.Selection.rangeObject,
124
- foundMarkup;
124
+ foundMarkup,
125
+ selectedCells = jQuery('.aloha-cell-selected');
126
+
127
+ // formating workaround for table plugin
128
+ if ( selectedCells.length > 0 ) {
129
+ var cellMarkupCounter = 0;
130
+ selectedCells.each( function () {
131
+ var cellContent = jQuery(this).find('div'),
132
+ cellMarkup = cellContent.find(button);
133
+
134
+ if ( cellMarkup.length > 0 ) {
135
+ // unwrap all found markup text
136
+ // <td><b>text</b> foo <b>bar</b></td>
137
+ // and wrap the whole contents of the <td> into <b> tags
138
+ // <td><b>text foo bar</b></td>
139
+ cellMarkup.contents().unwrap();
140
+ cellMarkupCounter++;
141
+ }
142
+ cellContent.contents().wrap('<'+button+'></'+button+'>');
143
+ });
144
+
145
+ // remove all markup if all cells have markup
146
+ if ( cellMarkupCounter == selectedCells.length ) {
147
+ selectedCells.find(button).contents().unwrap();
148
+ }
149
+ return false;
150
+ }
151
+ // formating workaround for table plugin
125
152
 
126
153
  // check whether the markup is found in the range (at the start of the range)
127
154
  foundMarkup = rangeObject.findMarkup(function() {
128
155
  return this.nodeName.toLowerCase() == markup.get(0).nodeName.toLowerCase();
129
156
  }, Aloha.activeEditable.obj);
130
157
 
131
- if (foundMarkup) {
158
+ if ( foundMarkup ) {
132
159
  // remove the markup
133
160
  if (rangeObject.isCollapsed()) {
134
161
  // when the range is collapsed, we remove exactly the one DOM element
@@ -176,6 +203,33 @@ function(Aloha, Plugin, jQuery, FloatingMenu, i18n, i18nCore) {
176
203
  'iconClass' : 'aloha-button ' + i18n.t('aloha-button-' + button),
177
204
  'markup' : jQuery('<'+button+'></'+button+'>'),
178
205
  'click' : function() {
206
+ var selectedCells = jQuery('.aloha-cell-selected');
207
+ // formating workaround for table plugin
208
+ if ( selectedCells.length > 0 ) {
209
+ var cellMarkupCounter = 0;
210
+ selectedCells.each( function () {
211
+ var cellContent = jQuery(this).find('div'),
212
+ cellMarkup = cellContent.find(button);
213
+
214
+ if ( cellMarkup.length > 0 ) {
215
+ // unwrap all found markup text
216
+ // <td><b>text</b> foo <b>bar</b></td>
217
+ // and wrap the whole contents of the <td> into <b> tags
218
+ // <td><b>text foo bar</b></td>
219
+ cellMarkup.contents().unwrap();
220
+ cellMarkupCounter++;
221
+ }
222
+ cellContent.contents().wrap('<'+button+'></'+button+'>');
223
+ });
224
+
225
+ // remove all markup if all cells have markup
226
+ if ( cellMarkupCounter == selectedCells.length ) {
227
+ selectedCells.find(button).contents().unwrap();
228
+ }
229
+ return false;
230
+ }
231
+ // formating workaround for table plugin
232
+
179
233
  Aloha.Selection.changeMarkupOnSelection(jQuery('<' + button + '></' + button + '>'));
180
234
  }
181
235
  });
@@ -1,5 +1,5 @@
1
1
  define({
2
- root: {"button.strong.tooltip":"Strong","button.em.tooltip":"Emphasize","button.b.tooltip":"Bold","button.i.tooltip":"Italic","button.u.tooltip":"Underline","button.cite.tooltip":"Cite","button.q.tooltip":"","button.code.tooltip":"Code","button.abbr.tooltip":"Abbreviation","button.del.tooltip":"Strikethrough","button.sub.tooltip":"Subscript","button.sup.tooltip":"Superscript","button.p.tooltip":"Paragraph","button.h1.tooltip":"Heading 1","button.h2.tooltip":"Heading 2","button.h3.tooltip":"Heading 3","button.h4.tooltip":"Heading 4","button.h5.tooltip":"Heading 5","button.h6.tooltip":"Heading 6","button.pre.tooltip":"Pre formated text","button.title.tooltip":"Title","button.removeFormat.tooltip":"Remove formatting","button.removeFormat.text":"Remove formatting","GENTICS_button_p":"GENTICS_button_p","GENTICS_button_h1":"GENTICS_button_h1","GENTICS_button_h2":"GENTICS_button_h2","GENTICS_button_h3":"GENTICS_button_h3","GENTICS_button_h4":"GENTICS_button_h4","GENTICS_button_h5":"GENTICS_button_h5","GENTICS_button_h6":"GENTICS_button_h6","GENTICS_button_pre":"GENTICS_button_pre","GENTICS_button_title":"GENTICS_button_title"}
2
+ root: {"button.strong.tooltip":"Strong","button.em.tooltip":"Emphasize","button.b.tooltip":"Bold","button.i.tooltip":"Italic","button.u.tooltip":"Underline","button.cite.tooltip":"Cite","button.q.tooltip":"","button.code.tooltip":"Code","button.abbr.tooltip":"Abbreviation","button.s.tooltip":"Strikethrough","button.del.tooltip":"Deleted","button.sub.tooltip":"Subscript","button.sup.tooltip":"Superscript","button.p.tooltip":"Paragraph","button.h1.tooltip":"Heading 1","button.h2.tooltip":"Heading 2","button.h3.tooltip":"Heading 3","button.h4.tooltip":"Heading 4","button.h5.tooltip":"Heading 5","button.h6.tooltip":"Heading 6","button.pre.tooltip":"Pre formated text","button.title.tooltip":"Title","button.removeFormat.tooltip":"Remove formatting","button.removeFormat.text":"Remove formatting","GENTICS_button_p":"GENTICS_button_p","GENTICS_button_h1":"GENTICS_button_h1","GENTICS_button_h2":"GENTICS_button_h2","GENTICS_button_h3":"GENTICS_button_h3","GENTICS_button_h4":"GENTICS_button_h4","GENTICS_button_h5":"GENTICS_button_h5","GENTICS_button_h6":"GENTICS_button_h6","GENTICS_button_pre":"GENTICS_button_pre","GENTICS_button_title":"GENTICS_button_title"}
3
3
  , "de":true,
4
4
  "eo":true,
5
5
  "fi":true,
@@ -17,9 +17,11 @@ function(Aloha, jQuery, Plugin, FloatingMenu, i18n, i18nCore) {
17
17
  this._super('horizontalruler');
18
18
  },
19
19
  languages: ['en'],
20
+ config: ['hr'],
20
21
  init: function() {
21
22
  var that = this;
22
- var insertButton = new Aloha.ui.Button({
23
+
24
+ this.insertButton = new Aloha.ui.Button({
23
25
  'name': 'hr',
24
26
  'iconClass': 'aloha-button-horizontalruler',
25
27
  'size': 'small',
@@ -29,11 +31,24 @@ function(Aloha, jQuery, Plugin, FloatingMenu, i18n, i18nCore) {
29
31
  });
30
32
  FloatingMenu.addButton(
31
33
  'Aloha.continuoustext',
32
- insertButton,
34
+ this.insertButton,
33
35
  i18nCore.t('floatingmenu.tab.insert'),
34
36
  1
35
37
  );
36
-
38
+
39
+ Aloha.bind( 'aloha-editable-activated', function ( event, rangeObject ) {
40
+ if (Aloha.activeEditable) {
41
+ that.cfg = that.getEditableConfig( Aloha.activeEditable.obj );
42
+
43
+ if ( jQuery.inArray( 'hr', that.cfg ) != -1 ) {
44
+ that.insertButton.show();
45
+ } else {
46
+ that.insertButton.hide();
47
+ return;
48
+ }
49
+ }
50
+ });
51
+
37
52
  },
38
53
  insertHR: function(character) {
39
54
  var self = this;
@@ -1,1615 +1,1643 @@
1
1
  /*
2
2
  * Aloha Image Plugin - Allow image manipulation in Aloha Editor
3
- *
3
+ *
4
4
  * Author & Copyright (c) 2011 Gentics Software GmbH
5
5
  * aloha-sales@gentics.com
6
- * Contributors
6
+ * Contributors
7
7
  * Johannes Schüth - http://jotschi.de
8
- * Nicolas karageuzian - http://nka.me/
9
- * Benjamin Athur Lupton - http://www.balupton.com/
10
- * Thomas Lete
11
- * Nils Dehl
12
- * Christopher Hlubek
13
- * Edward Tsech
14
- * Haymo Meran
8
+ * Nicolas karageuzian - http://nka.me/
9
+ * Benjamin Athur Lupton - http://www.balupton.com/
10
+ * Thomas Lete
11
+ * Nils Dehl
12
+ * Christopher Hlubek
13
+ * Edward Tsech
14
+ * Haymo Meran
15
15
  *
16
16
  * Licensed under the terms of http://www.aloha-editor.com/license.html
17
17
  */
18
18
 
19
19
  define([
20
- // js
21
- 'aloha/jquery',
22
- 'aloha/plugin',
23
- 'aloha/floatingmenu',
24
- 'i18n!aloha/nls/i18n',
25
- 'i18n!image/nls/i18n',
26
- 'jquery-plugin!image/vendor/ui/jquery-ui-1.8.10.custom.min',
27
- 'jquery-plugin!image/vendor/jcrop/jquery.jcrop.min',
28
- 'jquery-plugin!image/vendor/mousewheel/mousewheel',
29
- // css
30
- 'css!image/css/image.css',
31
- 'css!image/vendor/ui/ui-lightness/jquery-ui-1.8.10.cropnresize.css',
32
- 'css!image/vendor/jcrop/jquery.jcrop.css'
20
+ // js
21
+ 'aloha/jquery',
22
+ 'aloha/plugin',
23
+ 'aloha/floatingmenu',
24
+ 'i18n!aloha/nls/i18n',
25
+ 'i18n!image/nls/i18n',
26
+ 'jquery-plugin!image/vendor/ui/jquery-ui-1.8.10.custom.min',
27
+ 'jquery-plugin!image/vendor/jcrop/jquery.jcrop.min',
28
+ 'jquery-plugin!image/vendor/mousewheel/mousewheel',
29
+ // css
30
+ 'css!image/css/image.css',
31
+ 'css!image/vendor/ui/ui-lightness/jquery-ui-1.8.10.cropnresize.css',
32
+ 'css!image/vendor/jcrop/jquery.jcrop.css'
33
33
  ],
34
34
  function AlohaImagePlugin ( aQuery, Plugin, FloatingMenu, i18nCore, i18n ) {
35
-
36
-
37
-
38
- var jQuery = aQuery;
39
- var $ = aQuery;
40
- var GENTICS = window.GENTICS, Aloha = window.Aloha;
41
-
42
- // Attributes manipulation utilities
43
- // Aloha team may want to factorize, it could be useful for other plugins
44
- // Prototypes
45
- String.prototype.toInteger = String.prototype.toInteger || function() {
46
- return parseInt(String(this).replace(/px$/,'')||0,10);
47
- };
48
- String.prototype.toFloat = String.prototype.toInteger || function() {
49
- return parseFloat(String(this).replace(/px$/,'')||0,10);
50
- };
51
- Number.prototype.toInteger = Number.prototype.toInteger || String.prototype.toInteger;
52
- Number.prototype.toFloat = Number.prototype.toFloat || String.prototype.toFloat;
53
-
54
- // Insert jQuery Prototypes
55
- jQuery.extend(true, jQuery.fn, {
56
- increase: jQuery.fn.increase || function(attr) {
57
- var obj = jQuery(this), value, newValue;
58
- // Check
59
- if ( !obj.length ) {
60
- return obj;
61
- }
62
- // Calculate
63
- value = obj.css(attr).toFloat();
64
- newValue = Math.round((value||1)*1.2);
65
- // Apply
66
- if (value == newValue) { // when value is 2, won't increase
67
- newValue++;
68
- }
69
- // Apply
70
- obj.css(attr,newValue);
71
- // Chain
72
- return obj;
73
- },
74
- decrease: jQuery.fn.decrease || function(attr) {
75
- var obj = jQuery(this), value, newValue;
76
- // Check
77
- if ( !obj.length ) {
78
- return obj;
79
- }
80
- // Calculate
81
- value = obj.css(attr).toFloat();
82
- newValue = Math.round((value||0)*0.8);
83
- // Apply
84
- if (value == newValue && newValue >0) { // when value is 2, won't increase
85
- newValue--;
86
- }
87
- obj.css(attr,newValue);
88
- // Chain
89
- return obj;
90
- }
91
- });
92
-
93
- // Create and register Image Plugin
94
- return Plugin.create('image', {
95
-
96
- languages: ['en', 'fr', 'de', 'ru', 'cz'],
97
-
98
- defaultSettings: {
99
- 'maxWidth': 1600,
100
- 'minWidth': 3,
101
- 'maxHeight': 1200,
102
- 'minHeight': 3,
103
- // This setting will correct manually values that are out of bounds
104
- 'autoCorrectManualInput': true,
105
- // This setting will define a fixed aspect ratio for all resize actions
106
- 'fixedAspectRatio' : false,
107
- // When enabled this setting will order the plugin to automatically resize images to given bounds
108
- 'autoResize': false,
109
- //Image manipulation options - ONLY in default config section
110
- ui: {
111
- oneTab : false, //Place all ui components within one tab
112
- insert : true,
113
- reset : true,
114
- aspectRatioToggle: true, // Toggle button for the aspect ratio
115
- align : true, // Menu elements to show/hide in menu
116
- resize : true, // Resize buttons
117
- meta : true,
118
- margin : true,
119
- crop : true,
120
- resizable : true, // Resizable ui-drag image
121
- handles : 'ne, se, sw, nw'
122
- },
123
-
124
- /**
125
- * Crop callback is triggered after the user clicked accept to accept his crop
126
- * @param image jquery image object reference
127
- * @param props cropping properties
128
- */
129
- onCropped: function ($image, props) {
130
- Aloha.Log.info('Default onCropped invoked', $image, props);
131
- },
132
-
133
- /**
134
- * Reset callback is triggered before the internal reset procedure is applied
135
- * if this function returns true, then the reset has been handled by the callback
136
- * which means that no other reset will be applied
137
- * if false is returned the internal reset procedure will be applied
138
- * @param image jquery image object reference
139
- * @return true if a reset has been applied, false otherwise
140
- */
141
- onReset: function ($image) {
142
- Aloha.Log.info('Default onReset invoked', $image);
143
- return false;
144
- },
145
-
146
- /**
147
- * Example callback method which gets called while the resize process is beeing executed.
148
- */
149
- onResize: function ($image) {
150
- Aloha.Log.info('Default onResize invoked', $image);
151
- },
152
-
153
- /**
154
- * Resize callback is triggered after the internal resize procedure is applied.
155
- */
156
- onResized: function ($image) {
157
- Aloha.Log.info('Default onResized invoked', $image);
158
- }
159
- },
160
-
161
- /**
162
- * Internal callback hook which gets invoked when cropping has been finished
163
- */
164
- _onCropped: function ($image, props) {
165
-
166
- $('#' + this.imgResizeHeightField.id).val($image.height());
167
- $('#' + this.imgResizeWidthField.id).val($image.width());
168
-
169
-
170
- $('body').trigger('aloha-image-cropped', [$image, props]);
171
-
172
- // Call the custom onCropped function
173
- this.onCropped($image, props);
174
- },
175
-
176
- /**
177
- * Internal callback hook which gets invoked when resetting images
178
- */
179
- _onReset: function ($image) {
180
-
181
- $('#' + this.imgResizeHeightField.id).val($image.height());
182
- $('#' + this.imgResizeWidthField.id).val($image.width());
183
-
184
- // No default behaviour defined besides event triggering
185
- $('body').trigger('aloha-image-reset', $image);
186
-
187
- // Call the custom resize function
188
- return this.onReset($image);
189
- },
190
-
191
- /**
192
- * Internal callback hook which gets invoked while the image is beeing resized
193
- */
194
- _onResize: function ($image) {
195
-
196
- $('#' + this.imgResizeHeightField.id).val($image.height());
197
- $('#' + this.imgResizeWidthField.id).val($image.width());
198
-
199
- // No default behaviour defined besides event triggering
200
- $('body').trigger('aloha-image-resize', $image);
201
-
202
- // Call the custom resize function
203
- this.onResize($image);
204
- },
205
-
206
- /**
207
- * Internal callback hook which gets invoked when the current resizing action has stopped
208
- */
209
- _onResized: function ($image) {
210
-
211
- $('#' + this.imgResizeHeightField.id).val($image.height());
212
- $('#' + this.imgResizeWidthField.id).val($image.width());
213
-
214
- $('body').trigger('aloha-image-resized', $image);
215
-
216
- // Call the custom resize function
217
- this.onResized($image);
218
- },
219
-
220
- /**
221
- * The image that is currently edited
222
- */
223
- imageObj: null,
224
-
225
- /**
226
- * The Jcrop API reference
227
- * this is needed to be able to destroy the cropping frame later on
228
- * the variable is linked to the api object whilst cropping, or set to null otherwise
229
- * strange, but done as documented http://deepliquid.com/content/Jcrop_API.html
230
- */
231
- jcAPI: null,
232
-
233
-
234
- /**
235
- * State variable for the aspect ratio toggle feature
236
- */
237
- keepAspectRatio: false,
238
-
239
- /**
240
- * Variable that will hold the start aspect ratio. This ratio will be used once starResize will be called.
241
- */
242
- startAspectRatio: false,
243
-
244
- /**
245
- * This will contain an image's original properties to be able to undo previous settings
246
- *
247
- * when an image is clicked for the first time, a new object will be added to the array
248
- * {
249
- * obj : [the image object reference],
250
- * src : [the original src url],
251
- * width : [initial width],
252
- * height : [initial height]
253
- * }
254
- *
255
- * when an image is clicked the second time, the array will be checked for the image object
256
- * referenct, to prevent for double entries
257
- */
258
- restoreProps: [],
259
-
260
- objectTypeFilter: [],
261
-
262
- /**
263
- * Plugin initialization method
264
- */
265
- init: function() {
266
-
267
- var that = this;
268
-
269
- var imagePluginUrl = Aloha.getPluginUrl('image');
270
-
271
- // Extend the default settings with the custom ones (done by default)
272
- this.startAspectRatio = this.settings.fixedAspectRatio;
273
- this.config = this.defaultSettings;
274
- this.settings = jQuery.extend(true, this.defaultSettings, this.settings);
275
-
276
- that.initializeButtons();
277
- that.bindInteractions();
278
- that.subscribeEvents();
279
-
280
- },
281
-
282
- /**
283
- * Create buttons
284
- */
285
- initializeButtons: function() {
286
-
287
- var that = this,
288
- tabInsert = i18nCore.t('floatingmenu.tab.insert'),
289
- tabImage = i18n.t('floatingmenu.tab.img'),
290
- tabFormatting = i18n.t('floatingmenu.tab.formatting'),
291
- tabCrop = i18n.t('floatingmenu.tab.crop'),
292
- tabResize = i18n.t('floatingmenu.tab.resize');
293
-
294
- FloatingMenu.createScope(this.name, 'Aloha.empty');
295
-
296
- if (this.settings.ui.insert) {
297
- var tabId = this.settings.ui.oneTab ? tabImage : tabInsert;
298
- that._addUIInsertButton(tabId);
299
- }
300
-
301
- if (this.settings.ui.meta) {
302
- var tabId = this.settings.ui.oneTab ? tabImage : tabImage;
303
- that._addUIMetaButtons(tabId);
304
- }
305
-
306
- if (this.settings.ui.reset) {
307
- var tabId = this.settings.ui.reset ? tabImage : tabImage;
308
- that._addUIResetButton(tabId);
309
- }
310
-
311
- if (this.settings.ui.align) {
312
- var tabId = this.settings.ui.oneTab ? tabImage : tabFormatting;
313
- that._addUIAlignButtons(tabId);
314
- }
315
-
316
- if (this.settings.ui.margin) {
317
- var tabId = this.settings.ui.oneTab ? tabImage : tabFormatting;
318
- that._addUIMarginButtons(tabId);
319
- }
320
-
321
- if (this.settings.ui.crop) {
322
- var tabId = this.settings.ui.oneTab ? tabImage : tabCrop;
323
- that._addUICropButtons(tabId);
324
- }
325
-
326
- if (this.settings.ui.resize) {
327
- var tabId = this.settings.ui.oneTab ? tabImage : tabResize;
328
- that._addUIResizeButtons(tabId);
329
- }
330
-
331
- if (this.settings.ui.aspectRatioToggle) {
332
- var tabId = this.settings.ui.oneTab ? tabImage : tabResize;
333
- that.__addUIAspectRatioToggleButton(tabId);
334
- }
335
-
336
- // TODO fix the function and reenable this button
337
- //that._addNaturalSizeButton();
338
- },
339
-
340
-
341
- /**
342
- * Adds the aspect ratio toggle button to the floating menu
343
- */
344
- __addUIAspectRatioToggleButton: function(tabId) {
345
- var that = this;
346
- var toggleButton = new Aloha.ui.Button({
347
- 'size' : 'small',
348
- 'tooltip' : i18n.t('button.toggle.tooltip'),
349
- 'toggle' : true,
350
- 'iconClass' : 'cnr-ratio',
351
- 'onclick' : function (btn, event) {
352
- that.toggleKeepAspectRatio();
353
- }
354
- });
355
-
356
-
357
- // If the setting has been set to a number or false we need to activate the
358
- // toggle button to indicate that the aspect ratio will be preserved.
359
- if (this.settings.fixedAspectRatio != false) {
360
- toggleButton.pressed = true;
361
- this.keepAspectRatio = true;
362
- }
363
-
364
- FloatingMenu.addButton(
365
- that.name,
366
- toggleButton,
367
- tabId,
368
- 20
369
- );
370
-
371
-
372
- },
373
-
374
-
375
- /**
376
- * Adds the reset button to the floating menu for the given tab
377
- */
378
- _addUIResetButton: function(tabId) {
379
- var that = this;
380
- // Reset button
381
- var resetButton = new Aloha.ui.Button({
382
- 'size' : 'small',
383
- 'tooltip' : i18n.t('Reset'),
384
- 'toggle' : false,
385
- 'iconClass' : 'cnr-reset',
386
- 'onclick' : function (btn, event) {
387
- that.reset();
388
- }
389
- });
390
-
391
- FloatingMenu.addButton(
392
- that.name,
393
- resetButton,
394
- tabId,
395
- 2
396
- );
397
- },
398
-
399
- /**
400
- * Adds the insert button to the floating menu
401
- */
402
- _addUIInsertButton: function(tabId) {
403
- var that = this;
404
- this.insertImgButton = new Aloha.ui.Button({
405
- 'name' : 'insertimage',
406
- 'iconClass': 'aloha-button aloha-image-insert',
407
- 'size' : 'small',
408
- 'onclick' : function () { that.insertImg(); },
409
- 'tooltip' : i18n.t('button.addimg.tooltip'),
410
- 'toggle' : false
411
- });
412
-
413
- FloatingMenu.addButton(
414
- 'Aloha.continuoustext',
415
- this.insertImgButton,
416
- tabId,
417
- 1
418
- );
419
- },
420
-
421
- /**
422
- * Adds the ui meta fields (search, title) to the floating menu.
423
- */
424
- _addUIMetaButtons: function(tabId) {
425
- var that = this;
426
- var imgSrcLabel = new Aloha.ui.Button({
427
- 'label': i18n.t('field.img.src.label'),
428
- 'tooltip': i18n.t('field.img.src.tooltip'),
429
- 'size': 'small'
430
- });
431
- this.imgSrcField = new Aloha.ui.AttributeField({'name' : 'imgsrc'});
432
- this.imgSrcField.setObjectTypeFilter( this.objectTypeFilter );
433
-
434
- // add the title field for images
435
- var imgTitleLabel = new Aloha.ui.Button({
436
- 'label': i18n.t('field.img.title.label'),
437
- 'tooltip': i18n.t('field.img.title.tooltip'),
438
- 'size': 'small'
439
- });
440
-
441
- this.imgTitleField = new Aloha.ui.AttributeField();
442
- this.imgTitleField.setObjectTypeFilter();
443
- FloatingMenu.addButton(
444
- this.name,
445
- this.imgSrcField,
446
- tabId,
447
- 1
448
- );
449
-
450
- },
451
-
452
- /**
453
- * Adds the ui align buttons to the floating menu
454
- */
455
- _addUIAlignButtons: function(tabId) {
456
- var that = this;
457
-
458
- var alignLeftButton = new Aloha.ui.Button({
459
- 'iconClass': 'aloha-img aloha-image-align-left',
460
- 'size': 'small',
461
- 'onclick' : function() {
462
- var el = jQuery(that.findImgMarkup());
463
- el.add(el.parent()).css('float', 'left');
464
- },
465
- 'tooltip': i18n.t('button.img.align.left.tooltip')
466
- });
467
-
468
- FloatingMenu.addButton(
469
- that.name,
470
- alignLeftButton,
471
- tabId,
472
- 1
473
- );
474
-
475
- var alignRightButton = new Aloha.ui.Button({
476
- 'iconClass': 'aloha-img aloha-image-align-right',
477
- 'size': 'small',
478
- 'onclick' : function() {
479
- var el = jQuery(that.findImgMarkup());
480
- el.add(el.parent()).css('float', 'right');
481
- },
482
- 'tooltip': i18n.t('button.img.align.right.tooltip')
483
- });
484
-
485
- FloatingMenu.addButton(
486
- that.name,
487
- alignRightButton,
488
- tabId,
489
- 1
490
- );
491
-
492
- var alignNoneButton = new Aloha.ui.Button({
493
- 'iconClass': 'aloha-img aloha-image-align-none',
494
- 'size': 'small',
495
- 'onclick' : function() {
496
- var el = jQuery(that.findImgMarkup());
497
- el.add(el.parent()).css({
498
- 'float': 'none',
499
- display: 'inline-block'
500
- });
501
- },
502
- 'tooltip': i18n.t('button.img.align.none.tooltip')
503
- });
504
-
505
- FloatingMenu.addButton(
506
- that.name,
507
- alignNoneButton,
508
- tabId,
509
- 1
510
- );
511
-
512
- },
513
-
514
- /**
515
- * Adds the ui margin buttons to the floating menu
516
- */
517
- _addUIMarginButtons: function(tabId) {
518
- var that = this;
519
- var incPadding = new Aloha.ui.Button({
520
- iconClass: 'aloha-img aloha-image-padding-increase',
521
- toggle: false,
522
- size: 'small',
523
- onclick: function() {
524
- jQuery(that.findImgMarkup()).increase('padding');
525
- },
526
- tooltip: i18n.t('padding.increase')
527
- });
528
- FloatingMenu.addButton(
529
- that.name,
530
- incPadding,
531
- tabId,
532
- 2
533
- );
534
-
535
- var decPadding = new Aloha.ui.Button({
536
- iconClass: 'aloha-img aloha-image-padding-decrease',
537
- toggle: false,
538
- size: 'small',
539
- onclick: function() {
540
- jQuery(that.findImgMarkup()).decrease('padding');
541
- },
542
- tooltip: i18n.t('padding.decrease')
543
- });
544
- FloatingMenu.addButton(
545
- that.name,
546
- decPadding,
547
- tabId,
548
- 2
549
- );
550
- },
551
-
552
- /**
553
- * Adds the crop buttons to the floating menu
554
- */
555
- _addUICropButtons: function (tabId) {
556
- var that = this;
557
-
558
- FloatingMenu.createScope('Aloha.img', ['Aloha.global']);
559
-
560
- this.cropButton = new Aloha.ui.Button({
561
- 'size' : 'small',
562
- 'tooltip' : i18n.t('Crop'),
563
- 'toggle' : true,
564
- 'iconClass' : 'cnr-crop',
565
- 'onclick' : function (btn, event) {
566
- if (btn.pressed) {
567
- that.crop();
568
- } else {
569
- that.endCrop();
570
- }
571
- }
572
- });
573
-
574
- FloatingMenu.addButton(
575
- this.name,
576
- this.cropButton,
577
- tabId,
578
- 3
579
- );
580
-
581
- },
582
-
583
- /**
584
- * Adds the resize buttons to the floating menu
585
- */
586
- _addUIResizeButtons: function (tabId) {
587
- var that = this;
588
-
589
- // Manual resize fields
590
- this.imgResizeHeightField = new Aloha.ui.AttributeField();
591
- this.imgResizeHeightField.maxValue = that.settings.maxHeight;
592
- this.imgResizeHeightField.minValue = that.settings.minHeight;
593
-
594
- this.imgResizeWidthField = new Aloha.ui.AttributeField();
595
- this.imgResizeWidthField.maxValue = that.settings.maxWidth;
596
- this.imgResizeWidthField.minValue = that.settings.minWidth;
597
-
598
- this.imgResizeWidthField.width = 50;
599
- this.imgResizeHeightField.width = 50;
600
-
601
- var widthLabel = new Aloha.ui.Button({
602
- 'label': i18n.t('width'),
603
- 'tooltip': i18n.t('width'),
604
- 'size': 'small'
605
- });
606
-
607
- FloatingMenu.addButton(
608
- this.name,
609
- widthLabel,
610
- tabId,
611
- 30
612
- );
613
-
614
- FloatingMenu.addButton(
615
- this.name,
616
- this.imgResizeWidthField,
617
- tabId,
618
- 40
619
- );
620
-
621
-
622
- var heightLabel = new Aloha.ui.Button({
623
- 'label': i18n.t('height'),
624
- 'tooltip': i18n.t('height'),
625
- 'size': 'small'
626
- });
627
-
628
- FloatingMenu.addButton(
629
- this.name,
630
- heightLabel,
631
- tabId,
632
- 50
633
- );
634
-
635
- FloatingMenu.addButton(
636
- this.name,
637
- this.imgResizeHeightField,
638
- tabId,
639
- 60
640
- );
641
-
642
-
643
- },
644
-
645
- /**
646
- * Adds the natural size button to the floating menu
647
- */
648
- _addNaturalSizeButton: function () {
649
- var that = this;
650
- var naturalSize = new Aloha.ui.Button({
651
- iconClass: 'aloha-img aloha-image-size-natural',
652
- size: 'small',
653
- toggle: false,
654
- onclick: function() {
655
- var img = new Image();
656
- img.onload = function() {
657
- var myimage = that.findImgMarkup();
658
- if (that.settings.ui.resizable) {
659
- that.endResize();
660
- }
661
- jQuery(myimage).css({
662
- 'width': img.width + 'px',
663
- 'height': img.height + 'px',
664
- 'max-width': '',
665
- 'max-height': ''
666
- });
667
- if (that.settings.ui.resizable) {
668
- that.resize();
669
- }
670
- };
671
- img.src = that.findImgMarkup().src;
672
-
673
- },
674
- tooltip: i18n.t('size.natural')
675
- });
676
- FloatingMenu.addButton(
677
- this.name,
678
- naturalSize,
679
- tabResize,
680
- 2
681
- );
682
- },
683
-
684
- /**
685
- * Bind plugin interactions
686
- */
687
- bindInteractions: function () {
688
- var that = this;
689
-
690
- if (this.settings.ui.resizable) {
691
- try {
692
- // this will disable mozillas image resizing facilities
693
- document.execCommand( 'enableObjectResizing', false, false );
694
- } catch (e) {
695
- Aloha.Log.error( e, 'Could not disable enableObjectResizing' );
696
- // this is just for internet explorer, who will not support disabling enableObjectResizing
697
- }
698
- }
699
-
700
- if (this.settings.ui.meta) {
701
- // update image object when src changes
702
- this.imgSrcField.addListener('keyup', function(obj, event) {
703
- that.srcChange();
704
- });
705
-
706
- this.imgSrcField.addListener('blur', function(obj, event) {
707
- // TODO remove image or do something usefull if the user leaves the
708
- // image without defining a valid image src.
709
- var img = jQuery(obj.getTargetObject());
710
- if ( img.attr('src') === '' ) {
711
- img.remove();
712
- } // image removal when src field is blank
713
- });
714
- }
715
-
716
- // Override the default method by using the given one
717
- if (this.settings.onCropped && typeof this.settings.onCropped === "function") {
718
- this.onCropped = this.settings.onCropped;
719
- }
720
-
721
- // Override the default method by using the given one
722
- if (this.settings.onReset && typeof this.settings.onReset === "function") {
723
- this.onReset = this.settings.onReset;
724
- }
725
-
726
- // Override the default method by using the given one
727
- if (this.settings.onResized && typeof this.settings.onResized === "function") {
728
- this.onResized = this.settings.onResized;
729
- }
730
-
731
- // Override the default method by using the given one
732
- if (this.settings.onResize && typeof this.settings.onResize === "function") {
733
- this.onResize = this.settings.onResize;
734
- }
735
-
736
- },
737
-
738
- /**
739
- * Subscribe to Aloha events and DragAndDropPlugin Event
740
- */
741
- subscribeEvents: function() {
742
- var that = this;
743
- var config = this.settings;
744
-
745
- jQuery('img').filter(config.globalselector).unbind();
746
- jQuery('img').filter(config.globalselector).click(function(event) {
747
- that.clickImage(event);
748
- });
749
-
750
- Aloha.bind('aloha-drop-files-in-editable', function(event, data) {
751
- var img, len = data.filesObjs.length, fileObj, config;
752
-
753
- while (--len >= 0) {
754
- fileObj = data.filesObjs[len];
755
- if (fileObj.file.type.match(/image\//)) {
756
- config = that.getEditableConfig(data.editable);
757
- // Prepare
758
- img = jQuery('<img/>');
759
- img.css({
760
- "max-width": that.maxWidth,
761
- "max-height": that.maxHeight
762
- });
763
- img.attr('id',fileObj.id);
764
- if (typeof fileObj.src === 'undefined') {
765
- img.attr('src', fileObj.data );
766
- //fileObj.src = fileObj.data ;
767
- } else {
768
- img.attr('src',fileObj.src );
769
- }
770
- GENTICS.Utils.Dom.insertIntoDOM(img, data.range, jQuery(Aloha.activeEditable.obj));
771
- }
772
- }
773
-
774
- });
775
-
776
- /*
777
- * Add the event handler for selection change
778
- */
779
- Aloha.bind('aloha-selection-changed', function(event, rangeObject, originalEvent) {
780
- var config, foundMarkup;
781
- if (originalEvent && originalEvent.target) {
782
- // Check if the element is currently beeing resized
783
- if (that.settings.ui.resizable && !jQuery(originalEvent.target).hasClass('ui-resizable-handle')) {
784
- that.endResize();
785
- }
786
- }
787
-
788
- if (Aloha.activeEditable !== null) {
789
- foundMarkup = that.findImgMarkup( rangeObject );
790
- //var config = that.getEditableConfig(Aloha.activeEditable.obj);
791
- config = that.getEditableConfig(Aloha.activeEditable.obj);
792
-
793
- if (typeof config !== 'undefined' ) {
794
- that.insertImgButton.show();
795
- } else {
796
- that.insertImgButton.hide();
797
- return;
798
- }
799
-
800
- // Enable image specific ui components if the element is an image
801
- if (foundMarkup) {
802
- that.insertImgButton.hide();
803
- FloatingMenu.setScope(that.name);
804
- if (that.settings.ui.meta) {
805
- that.imgSrcField.setTargetObject(foundMarkup, 'src');
806
- that.imgTitleField.setTargetObject(foundMarkup, 'title');
807
- }
808
- that.imgSrcField.focus();
809
- FloatingMenu.activateTabOfButton('imgsrc');
810
- } else {
811
- if (that.settings.ui.meta) {
812
- that.imgSrcField.setTargetObject(null);
813
- }
814
- }
815
- // TODO this should not be necessary here!
816
- FloatingMenu.doLayout();
817
- }
818
-
819
- });
820
-
821
- Aloha.bind('aloha-editable-created', function( event, editable) {
822
-
823
- try {
824
- // this will disable mozillas image resizing facilities
825
- document.execCommand( 'enableObjectResizing', false, false);
826
- } catch (e) {
827
- Aloha.Log.error( e, 'Could not disable enableObjectResizing');
828
- // this is just for others, who will not support disabling enableObjectResizing
829
- }
830
-
831
- // Inital click on images will be handled here
832
- // editable.obj.find('img').attr('_moz_resizing', false);
833
- // editable.obj.find('img').contentEditable(false);
834
- editable.obj.delegate( 'img', 'mouseup', function (event) {
835
- that.clickImage(event);
836
- event.stopPropagation();
837
- });
838
- });
839
-
840
- that._subscribeToResizeFieldEvents();
841
-
842
- },
843
-
844
- /**
845
- * Automatically resize the image to fit into defined bounds.
846
- */
847
- autoResize: function() {
848
- var that = this;
849
-
850
- var width = that.imageObj.width();
851
- var height = that.imageObj.height();
852
-
853
- // Only normalize the field values when the image exeeds the definded bounds
854
- if (width < that.settings.minWidth || width > that.settings.maxWidth || height < that.settings.minHeight || height > that.settings.maxHeight) {
855
- that._setNormalizedFieldValues('width');
856
- that.setSizeByFieldValue();
857
- return true;
858
- } else {
859
- return false;
860
- }
861
- },
862
-
863
- /**
864
- * Toggle the keep aspect ratio functionallity
865
- */
866
- toggleKeepAspectRatio: function() {
867
-
868
- this.keepAspectRatio = !this.keepAspectRatio;
869
-
870
- this.endResize();
871
- if (!this.keepAspectRatio) {
872
- this.startAspectRatio = false;
873
- } else {
874
- // If no fixed aspect ratio was given we will calculate a new start
875
- // aspect ratio that will be used for the next starResize action.
876
- if ( typeof this.settings.fixedAspectRatio !== 'number' ) {
877
- var currentRatio = this.imageObj.width() / this.imageObj.height();
878
- this.startAspectRatio = currentRatio;
879
- } else {
880
- this.startAspectRatio = this.settings.fixedAspectRatio;
881
- }
882
- }
883
- this.startResize();
884
- },
885
-
886
- /**
887
- * Bind interaction events that are invoked on the resize fields
888
- */
889
- _subscribeToResizeFieldEvents: function() {
890
- var that = this;
891
-
892
- /**
893
- * Helper function that will update the fields
894
- */
895
- function updateField( $field, delta, maxValue, minValue ) {
896
-
897
- if ( typeof minValue === 'undefined' ) {
898
- minValue = 0;
899
- }
900
-
901
- if ( typeof maxValue === 'undefined' ) {
902
- maxValue = 8000;
903
- }
904
-
905
- // If the current value of the field can't be parsed we don't update it
906
- var oldValue = parseInt( $field.val() );
907
- if ( isNaN(oldValue) ) {
908
- $field.css( 'background-color', 'red' );
909
- return false;
910
- }
911
-
912
- var newValue = oldValue + delta;
913
- // Exit if the newValue is above the maxValue limit (only if the user tries to increment)
914
- if (delta>=0 && newValue > maxValue) {
915
-
916
- // Auto correct out of bounds values
917
- if (that.settings.autoCorrectManualInput) {
918
- $field.val(maxValue);
919
- return true;
920
- } else {
921
- $field.css('background-color','red');
922
- return false;
923
- }
924
- // Exit if the newValue is below the minValue (only if the user tries to decrement)
925
- } else if (delta<=0 && newValue<minValue) {
926
-
927
- // Auto correct out of bounds values
928
- if (that.settings.autoCorrectManualInput) {
929
- $field.val(minValue);
930
- return true;
931
- } else {
932
- $field.css('background-color','red');
933
- return false;
934
- }
935
- } else {
936
- $field.css('background-color','');
937
- }
938
- $field.val(oldValue + delta);
939
- return true;
940
- };
941
-
942
- /**
943
- * Handle the keyup event on the field
944
- */
945
- function handleKeyUpEventOnField(e) {
946
-
947
- // Load the max/min from the data properties of this event
948
- var minValue = e.data.minValue;
949
- var maxValue = e.data.maxValue;
950
- var fieldName = e.data.fieldName;
951
-
952
- // Allow backspace and delete
953
- if (e.keyCode == 8 || e.keyCode == 46) {
954
- if($(this).val() >= minValue) {
955
-
956
- // Check if we are currently in cropping mode
957
- if(typeof that.jcAPI !== 'undefined' && that.jcAPI != null) {
958
- that.setCropAreaByFieldValue();
959
- } else {
960
- // 1. Normalize the size
961
- that._setNormalizedFieldValues(fieldName);
962
- // 2. Set the final size to the image
963
- that.setSizeByFieldValue();
964
- }
965
- }
966
- // 0-9 keys
967
- } else if (e.keyCode <= 57 && e.keyCode >= 48 || e.keyCode <= 105 && e.keyCode >= 96 ) {
968
- if($(this).val() >= minValue) {
969
-
970
- // Check if we are currently in cropping mode
971
- if(typeof that.jcAPI !== 'undefined' && that.jcAPI != null) {
972
- that.setCropAreaByFieldValue();
973
- } else {
974
- // 1. Normalize the size
975
- that._setNormalizedFieldValues(fieldName);
976
- // 2. Set the final size to the image
977
- that.setSizeByFieldValue();
978
- }
979
- }
980
- } else {
981
- var delta = 0;
982
- if (e.keyCode == 38 || e.keyCode == 107) {
983
- delta = +1;
984
- } else if (e.keyCode == 40 || e.keyCode == 109) {
985
- delta = -1;
986
- }
987
- // Handle key combinations
988
- if ( e.shiftKey || e.metaKey || e.ctrlKey ) {
989
- delta = delta * 10;
990
- }
991
-
992
- // Only resize when field values are ok
993
- if(updateField($(this), delta, maxValue, minValue)) {
994
- // Check if we are currently in cropping mode
995
- if(typeof that.jcAPI !== 'undefined' && that.jcAPI != null) {
996
- that.setCropAreaByFieldValue();
997
- } else {
998
- // 1. Normalize the size
999
- that._setNormalizedFieldValues(fieldName);
1000
- // 2. Set the final size to the image
1001
- that.setSizeByFieldValue();
1002
- }
1003
- }
1004
- }
1005
-
1006
- e.preventDefault();
1007
- return false;
1008
- };
1009
-
1010
- /**
1011
- * Handle the mouse wheel event on the field
1012
- */
1013
- function handleMouseWheelEventOnField(e, delta) {
1014
- var minValue = e.data.minValue;
1015
- var maxValue = e.data.maxValue;
1016
- var fieldName = e.data.fieldName;
1017
-
1018
- // Handle key combinations
1019
- if ( e.shiftKey || e.metaKey || e.ctrlKey ) {
1020
- delta = delta * 10;
1021
- }
1022
-
1023
- // Only resize when field values are ok
1024
- if(updateField($(this), delta, maxValue, minValue)) {
1025
-
1026
- // Check if we are currently in cropping mode
1027
- if(typeof that.jcAPI !== 'undefined' && that.jcAPI != null) {
1028
- that.setCropAreaByFieldValue();
1029
- } else {
1030
- // 1. Normalize the size
1031
- that._setNormalizedFieldValues(fieldName);
1032
- // 2. Set the final size to the image
1033
- that.setSizeByFieldValue();
1034
- }
1035
- }
1036
- return false;
1037
- };
1038
-
1039
- /**
1040
- * Handle mousewheel,keyup actions on both fields
1041
- */
1042
- var $heightField = $('#' + that.imgResizeHeightField.id );
1043
- var heightEventData = {fieldName: 'height', maxValue: that.imgResizeHeightField.maxValue, minValue: that.imgResizeHeightField.minValue };
1044
- $heightField.live('keyup', heightEventData, handleKeyUpEventOnField);
1045
- $heightField.live('mousewheel', heightEventData, handleMouseWheelEventOnField);
1046
-
1047
- var $widthField = $('#' + that.imgResizeWidthField.id );
1048
- var widthEventData = {fieldName: 'width', maxValue: that.imgResizeWidthField.maxValue , minValue: that.imgResizeWidthField.minValue };
1049
- $widthField.live('keyup',widthEventData , handleKeyUpEventOnField);
1050
- $widthField.live('mousewheel', widthEventData, handleMouseWheelEventOnField);
1051
-
1052
- },
1053
-
1054
-
1055
- /**
1056
- * This helper function will keep the aspect ratio for the field with the given name.
1057
- */
1058
- _setNormalizedFieldValues: function(primaryFieldName) {
1059
-
1060
- var that = this;
1061
- var widthField = jQuery("#" + that.imgResizeWidthField.id);
1062
- var heightField = jQuery("#" + that.imgResizeHeightField.id);
1063
- var width = widthField.val();
1064
- var height = heightField.val();
1065
-
1066
- var size = that._normalizeSize(width, height, primaryFieldName);
1067
-
1068
- widthField.val(size.width);
1069
- heightField.val(size.height);
1070
-
1071
- },
1072
-
1073
- /**
1074
- * Manually set the given size for the current image
1075
- */
1076
- setSize: function(width, height) {
1077
-
1078
- var that = this;
1079
- this.imageObj.width(width);
1080
- this.imageObj.height(height);
1081
- var $wrapper = this.imageObj.closest('.Aloha_Image_Resize');
1082
- $wrapper.height(height);
1083
- $wrapper.width(width);
1084
-
1085
- this._onResize(this.imageObj);
1086
- this._onResized(this.imageObj);
1087
- },
1088
-
1089
- /**
1090
- * This method will handle the mouseUp event on images (eg. within editables).
1091
- * It will if enabled activate the resizing action.
1092
- */
1093
- clickImage: function( e ) {
1094
-
1095
- var that = this;
1096
- that.imageObj = jQuery(e.target);
1097
- var currentImage = that.imageObj;
1098
-
1099
- FloatingMenu.setScope(that.name);
1100
-
1101
- var editable = currentImage.closest('.aloha-editable');
1102
-
1103
- // Disabling the content editable. This will disable the resizeHandles in internet explorer
1104
- jQuery(editable).contentEditable(false);
1105
-
1106
- //Store the current props of the image
1107
- this.restoreProps.push({
1108
- obj : e.srcElement,
1109
- src : that.imageObj.attr('src'),
1110
- width : that.imageObj.width(),
1111
- height : that.imageObj.height()
1112
- });
1113
-
1114
- // Update the resize input fields with the new width and height
1115
- $('#' + that.imgResizeHeightField.id).val(that.imageObj.height());
1116
- $('#' + that.imgResizeWidthField.id).val(that.imageObj.width());
1117
-
1118
-
1119
- if (this.settings.ui.resizable) {
1120
- this.startResize();
1121
- }
1122
-
1123
-
1124
- if (this.settings.autoResize) {
1125
- this.autoResize();
1126
- }
1127
-
1128
- },
1129
-
1130
- /**
1131
- * This method extracts determins if the range selection contains an image
1132
- */
1133
- findImgMarkup: function ( range ) {
1134
-
1135
- var that = this;
1136
- var config = this.config;
1137
- var result, targetObj;
1138
-
1139
- if ( typeof range === 'undefined' ) {
1140
- range = Aloha.Selection.getRangeObject();
1141
- }
1142
-
1143
- targetObj = jQuery(range.startContainer);
1144
-
1145
- try {
1146
- if ( Aloha.activeEditable ) {
1147
- if (( typeof range.startContainer !== 'undefined'
1148
- && typeof range.startContainer.childNodes !== 'undefined'
1149
- && typeof range.startOffset !== 'undefined'
1150
- && typeof range.startContainer.childNodes[range.startOffset] !== 'undefined'
1151
- && range.startContainer.childNodes[range.startOffset].nodeName.toLowerCase() === 'img'
1152
- && range.startOffset+1 === range.endOffset) ||
1153
- (targetObj.hasClass('Aloha_Image_Resize')))
1154
- {
1155
- result = targetObj.find('img')[0];
1156
- if (! result.css) {
1157
- result.css = '';
1158
- }
1159
-
1160
- if (! result.title) {
1161
- result.title = '';
1162
- }
1163
-
1164
- if (! result.src) {
1165
- result.src = '';
1166
- }
1167
- return result;
1168
- }
1169
- else {
1170
- return null;
1171
- }
1172
- }
1173
- } catch (e) {
1174
- Aloha.Log.debug(e, "Error finding img markup.");
1175
- }
1176
- return null;
1177
-
1178
- },
1179
-
1180
-
1181
- /**
1182
- * This helper function will calculate the new width and height while keeping
1183
- * the aspect ratio when the keepAspectRatio flat is set to true. The primarySize
1184
- * can be 'width' or 'height'. The function will first try to normalize the oposite size.
1185
- */
1186
- _normalizeSize: function(width, height, primarySize) {
1187
-
1188
- var that = this;
1189
- // Convert string values to numbers
1190
- width = parseInt(width);
1191
- height = parseInt(height);
1192
-
1193
- /**
1194
- * Inner function that calculates the new height by examining the width
1195
- */
1196
- function handleHeight(callHandleWidth) {
1197
-
1198
- // Check whether the value is within bounds
1199
- if (height > that.settings.maxHeight) {
1200
-
1201
- // Throw a notification event
1202
- var eventProps = { 'org': height, 'new': that.settings.maxHeight};
1203
- $('body').trigger('aloha-image-resize-outofbounds', ["height", "max", eventProps]);
1204
- height = that.settings.maxHeight;
1205
-
1206
- } else if (height < that.settings.minHeight) {
1207
-
1208
- // Throw a notification event
1209
- var eventProps = { 'org': height, 'new': that.settings.minHeight};
1210
- $('body').trigger('aloha-image-resize-outofbounds', ["height", "min", eventProps]);
1211
- height = that.settings.minHeight;
1212
- }
1213
-
1214
- if (that.keepAspectRatio) {
1215
- width = height * aspectRatio;
1216
-
1217
- // We don't want to invoke handleWidth again. This would mess up our previously calculated width
1218
- if (callHandleWidth) {
1219
- handleWidth(false);
1220
- }
1221
- }
1222
-
1223
-
1224
- }
1225
-
1226
- /**
1227
- * Inner function that calculates the new width by examining the width
1228
- */
1229
- function handleWidth(callHandleHeight) {
1230
-
1231
- // Check whether the value is within bounds
1232
- if (width > that.settings.maxWidth) {
1233
-
1234
- // Throw a notification event
1235
- var eventProps = { 'org': width, 'new': that.settings.maxWidth};
1236
- $('body').trigger('aloha-image-resize-outofbounds', ["width", "max", eventProps]);
1237
-
1238
- width = that.settings.maxWidth;
1239
- } else if (width < that.settings.minWidth) {
1240
-
1241
- // Throw a notification event
1242
- var eventProps = { 'org': width, 'new': that.settings.minWidth};
1243
- $('body').trigger('aloha-image-resize-outofbounds', ["width", "min", eventProps]);
1244
-
1245
- width = that.settings.minWidth;
1246
- }
1247
-
1248
- // Calculate the new height
1249
- if (that.keepAspectRatio) {
1250
- height = width / aspectRatio;
1251
-
1252
- // We don't want to invoke handleHeight again. This would mess up our previously calculated height
1253
- if (callHandleHeight) {
1254
- handleHeight(false);
1255
- }
1256
-
1257
- }
1258
-
1259
- }
1260
-
1261
- // Load the aspect ratio and use the 4:3 ratio as default value.
1262
- var aspectRatio = 1.33333;
1263
- if (typeof that.startAspectRatio === 'number') {
1264
- aspectRatio = that.startAspectRatio;
1265
- }
1266
-
1267
- // Determin which size should be handled
1268
- if (primarySize == 'width') {
1269
- handleWidth(true);
1270
- }
1271
-
1272
- if (primarySize == 'height') {
1273
- handleHeight(true);
1274
- }
1275
-
1276
- // Floor the values return them
1277
- return {'width': Math.floor(width), 'height': Math.floor(height)};
1278
- },
1279
-
1280
-
1281
- /**
1282
- * Helper function that will set the new image size using the field values
1283
- */
1284
- setSizeByFieldValue: function() {
1285
- var that = this;
1286
- var width = $('#' + that.imgResizeWidthField.id ).val();
1287
- var height = $('#' + that.imgResizeHeightField.id ).val();
1288
- that.setSize(width, height);
1289
- },
1290
-
1291
- /**
1292
- * Helper function that will set the new crop area width and height using the field values
1293
- */
1294
- setCropAreaByFieldValue: function() {
1295
- var that = this;
1296
- var currentCropArea = that.jcAPI.tellSelect();
1297
-
1298
- var width = $('#' + that.imgResizeWidthField.id ).val();
1299
- width = parseInt(width);
1300
- var height = $('#' + that.imgResizeHeightField.id ).val();
1301
- height = parseInt(height);
1302
-
1303
- var selection = [currentCropArea['x'], currentCropArea['y'], currentCropArea['x'] + width,currentCropArea['y'] + height];
1304
- that.jcAPI.setSelect(selection);
1305
- },
1306
-
1307
- /**
1308
- * This method will insert a new image dom element into the dom tree
1309
- */
1310
- insertImg: function() {
1311
- var range = Aloha.Selection.getRangeObject(),
1312
- config = this.getEditableConfig(Aloha.activeEditable.obj),
1313
- imagePluginUrl = Aloha.getPluginUrl('image'),
1314
- imagestyle, imagetag, newImg;
1315
-
1316
- if ( range.isCollapsed() ) {
1317
- // TODO I would suggest to call the srcChange method. So all image src
1318
- // changes are on one single point.
1319
- imagestyle = "max-width: " + config.maxWidth + "; max-height: " + config.maxHeight;
1320
- imagetag = '<img style="'+ imagestyle + '" src="' + imagePluginUrl + '/img/blank.jpg" title="" />';
1321
- newImg = jQuery(imagetag);
1322
- // add the click selection handler
1323
- //newImg.click( Aloha.Image.clickImage ); - Using delegate now
1324
- GENTICS.Utils.Dom.insertIntoDOM(newImg, range, jQuery(Aloha.activeEditable.obj));
1325
-
1326
- } else {
1327
- Aloha.Log.error('img cannot markup a selection');
1328
- // TODO the desired behavior could be me the selected content is
1329
- // replaced by an image.
1330
- // TODO it should be editor's choice, with an NON-Ext Dialog instead of alert
1331
-
1332
- }
1333
- },
1334
-
1335
- srcChange: function () {
1336
- // TODO the src changed. I suggest :
1337
- // 1. set an loading image (I suggest set src base64 enc) to show the user
1338
- // we are trying to load an image
1339
- // 2. start a request to get the image
1340
- // 3a. the image is ok change the src
1341
- // 3b. the image is not availbable show an error.
1342
- this.imageObj.attr('src', this.imgSrcField.getQueryValue() ); // (the img tag)
1343
- // jQuery(img).attr('src', this.imgSrcField.getQueryValue() ); // (the query value in the inputfield)
1344
- // this.imgSrcField.getItem(); // (optinal a selected resource item)
1345
- // TODO additionally implement an srcChange Handler to let implementer
1346
- // customize
1347
- },
1348
-
1349
- /**
1350
- * Code imported from CropnResize Plugin
1351
- *
1352
- */
1353
- initCropButtons: function() {
1354
- var that = this,
1355
- btns,
1356
- oldLeft = 0,
1357
- oldTop = 0;
1358
-
1359
- jQuery('body').append(
1360
- '<div id="aloha-CropNResize-btns">\
1361
- <button class="cnr-crop-apply" title="' + i18n.t('Accept') + '">&#10004;</button>\
1362
- <button class="cnr-crop-cancel" title="' + i18n.t('Cancel') + '">&#10006;</button>\
1363
- </div>'
1364
- );
1365
-
1366
- btns = jQuery('#aloha-CropNResize-btns')
1367
-
1368
- btns.find('.cnr-crop-apply').click(function () {
1369
- that.acceptCrop();
1370
- });
1371
-
1372
- btns.find('.cnr-crop-cancel').click(function () {
1373
- that.endCrop();
1374
- });
1375
-
1376
- this.interval = setInterval(function () {
1377
- var jt = jQuery('.jcrop-tracker:first'),
1378
- off = jt.offset(),
1379
- jtt = off.top,
1380
- jtl = off.left,
1381
- jth = jt.height(),
1382
- jtw = jt.width();
1383
-
1384
- if (jth && jtw) {
1385
- btns.fadeIn('slow');
1386
- }
1387
-
1388
- // move the icons to the bottom right side
1389
- jtt = parseInt(jtt + jth + 3, 10);
1390
- jtl = parseInt(jtl + jtw - 55, 10);
1391
-
1392
- // comparison to old values hinders flickering bug in FF
1393
- if (oldLeft != jtl || oldTop != jtt) {
1394
- btns.offset({top: jtt, left: jtl});
1395
- }
1396
-
1397
- oldLeft = jtl;
1398
- oldTop = jtt;
1399
- }, 10);
1400
- },
1401
-
1402
- /**
1403
- * Destroy crop confirm and cancel buttons
1404
- */
1405
- destroyCropButtons: function () {
1406
- jQuery('#aloha-CropNResize-btns').remove();
1407
- clearInterval(this.interval);
1408
- },
1409
-
1410
- /**
1411
- * Helper function that will disable selectability of elements
1412
- */
1413
- _disableSelection: function (el) {
1414
- el.find('*').attr('unselectable', 'on')
1415
- .css({
1416
- '-moz-user-select':'none',
1417
- '-webkit-user-select':'none',
1418
- 'user-select':'none'
1419
- });
1420
- /*
1421
- .each(function() {
1422
- this.onselectstart = function () { return false; };
1423
- });
1424
- */
1425
-
1426
- },
1427
-
1428
- /**
1429
- * Initiate a crop action
1430
- */
1431
- crop: function () {
1432
- var that = this;
1433
- var config = this.config;
1434
-
1435
- this.initCropButtons();
1436
- if (this.settings.ui.resizable) {
1437
- this.endResize();
1438
- }
1439
-
1440
- this.jcAPI = jQuery.Jcrop(this.imageObj, {
1441
- onSelect : function () {
1442
- that._onCropSelect();
1443
- // ugly hack to keep scope :(
1444
- setTimeout(function () {
1445
- FloatingMenu.setScope(that.name);
1446
- }, 10);
1447
- }
1448
- });
1449
-
1450
- that._disableSelection($('.jcrop-holder'));
1451
- that._disableSelection($('#imageContainer'));
1452
- that._disableSelection($('#aloha-CropNResize-btns'));
1453
- $('body').trigger('aloha-image-crop-start', [this.imageObj]);
1454
- },
1455
-
1456
- /**
1457
- * Internal on crop select method
1458
- */
1459
- _onCropSelect: function() {
1460
- var that = this;
1461
-
1462
- // Update the width and height field using the intiial active crop area values
1463
- if(typeof that.jcAPI !== 'undefined' && that.jcAPI != null) {
1464
- var currentCropArea = that.jcAPI.tellSelect();
1465
- var widthField = jQuery("#" + that.imgResizeWidthField.id).val(currentCropArea['w']);
1466
- var heightField = jQuery("#" + that.imgResizeHeightField.id).val(currentCropArea['h']);
1467
- }
1468
-
1469
- },
1470
-
1471
-
1472
- /**
1473
- * Terminates a crop
1474
- */
1475
- endCrop: function () {
1476
- if ( this.jcAPI ) {
1477
- this.jcAPI.destroy();
1478
- this.jcAPI = null;
1479
- }
1480
-
1481
- this.destroyCropButtons();
1482
- this.cropButton.extButton.toggle(false);
1483
-
1484
- if ( this.settings.ui.resizable ) {
1485
- this.startResize();
1486
- }
1487
-
1488
- if ( this.keepAspectRatio ) {
1489
- var currentRatio = this.imageObj.width() / this.imageObj.height();
1490
- this.startAspectRatio = currentRatio;
1491
- }
1492
-
1493
- $('body').trigger('aloha-image-crop-stop', [this.imageObj]);
1494
- },
1495
-
1496
- /**
1497
- * Accept the current cropping area and apply the crop
1498
- */
1499
- acceptCrop: function () {
1500
- this._onCropped ( this.imageObj, this.jcAPI.tellSelect() );
1501
- this.endCrop ();
1502
- },
1503
-
1504
- /**
1505
- * This method will activate the jquery-ui resize functionality for the current image
1506
- */
1507
- startResize: function () {
1508
- var that = this;
1509
- var currentImageObj = this.imageObj;
1510
-
1511
- currentImageObj = this.imageObj.css({
1512
- height : this.imageObj.height(),
1513
- width : this.imageObj.width(),
1514
- position : 'relative',
1515
- 'max-height': '',
1516
- 'max-width' : ''
1517
- });
1518
-
1519
- currentImageObj.resizable({
1520
-
1521
- maxHeight : that.settings.maxHeight,
1522
- minHeight : that.settings.minHeight,
1523
- maxWidth : that.settings.maxWidth,
1524
- minWidth : that.settings.minWidth,
1525
- aspectRatio : that.startAspectRatio,
1526
- handles: that.settings.handles,
1527
- grid : that.settings.grid,
1528
- resize: function(event, ui) {
1529
- that._onResize(that.imageObj);
1530
- },
1531
- stop : function (event, ui) {
1532
- that._onResized(that.imageObj);
1533
-
1534
- // Workaround to finish cropping
1535
- if (this.enableCrop) {
1536
- setTimeout(function () {
1537
- FloatingMenu.setScope(that.name);
1538
- that.done(event);
1539
- }, 10);
1540
- }
1541
- }
1542
-
1543
- });
1544
-
1545
- currentImageObj.css('display', 'inline-block');
1546
-
1547
- // this will prevent the user from resizing an image
1548
- // using IE's resize handles
1549
- // however I could not manage to hide them completely
1550
- jQuery('.ui-wrapper')
1551
- .attr('contentEditable', false)
1552
- .addClass('aloha-image-box-active Aloha_Image_Resize aloha')
1553
- .css({
1554
- position: 'relative',
1555
- display: 'inline-block',
1556
- 'float': that.imageObj.css('float')
1557
- })
1558
- .bind('resizestart', function (e) {
1559
- e.preventDefault();
1560
- })
1561
- .bind('mouseup', function (e) {
1562
- e.originalEvent.stopSelectionUpdate = true;
1563
- });
1564
- },
1565
-
1566
- /**
1567
- * This method will end resizing and toggle buttons accordingly and remove all markup that has been added for cropping
1568
- */
1569
- endResize: function () {
1570
- // Find the nearest contenteditable and reenable it since resizing is finished
1571
- if (this.imageObj) {
1572
- var editable = this.imageObj.closest('.aloha-editable');
1573
- jQuery(editable).contentEditable(true);
1574
- }
1575
-
1576
- if (this.imageObj) {
1577
- this.imageObj
1578
- .resizable('destroy')
1579
- .css({
1580
- top : 0,
1581
- left : 0
1582
- });
1583
- }
1584
- },
1585
-
1586
- /**
1587
- * Reset the image to it's original properties
1588
- */
1589
- reset: function() {
1590
- if (this.settings.ui.crop) {
1591
- this.endCrop();
1592
- }
1593
-
1594
- if (this.settings.ui.resizable) {
1595
- this.endResize();
1596
- }
1597
-
1598
- if (this._onReset(this.imageObj)) {
1599
- // the external reset procedure has already performed a reset, so there is no need to apply an internal reset
1600
- return;
1601
- }
1602
-
1603
- for (var i=0;i<this.restoreProps.length;i++) {
1604
- // restore from restoreProps if there is a match
1605
- if (this.imageObj.get(0) === this.restoreProps[i].obj) {
1606
- this.imageObj.attr('src', this.restoreProps[i].src);
1607
- this.imageObj.width(this.restoreProps[i].width);
1608
- this.imageObj.height(this.restoreProps[i].height);
1609
- return;
1610
- }
1611
- }
1612
- }
1613
- });
35
+
36
+
37
+
38
+ var jQuery = aQuery;
39
+ var $ = aQuery;
40
+ var GENTICS = window.GENTICS;
41
+ var Aloha = window.Aloha;
42
+
43
+ // Attributes manipulation utilities
44
+ // Aloha team may want to factorize, it could be useful for other plugins
45
+ // Prototypes
46
+ String.prototype.toInteger = String.prototype.toInteger || function() {
47
+ return parseInt(String(this).replace(/px$/,'')||0,10);
48
+ };
49
+ String.prototype.toFloat = String.prototype.toInteger || function() {
50
+ return parseFloat(String(this).replace(/px$/,'')||0,10);
51
+ };
52
+ Number.prototype.toInteger = Number.prototype.toInteger || String.prototype.toInteger;
53
+ Number.prototype.toFloat = Number.prototype.toFloat || String.prototype.toFloat;
54
+
55
+ // Insert jQuery Prototypes
56
+ jQuery.extend(true, jQuery.fn, {
57
+ increase: jQuery.fn.increase || function(attr) {
58
+ var obj = jQuery(this), value, newValue;
59
+ // Check
60
+ if ( !obj.length ) {
61
+ return obj;
62
+ }
63
+ // Calculate
64
+ value = obj.css(attr).toFloat();
65
+ newValue = Math.round((value||1)*1.2);
66
+ // Apply
67
+ if (value == newValue) { // when value is 2, won't increase
68
+ newValue++;
69
+ }
70
+ // Apply
71
+ obj.css(attr,newValue);
72
+ // Chain
73
+ return obj;
74
+ },
75
+ decrease: jQuery.fn.decrease || function(attr) {
76
+ var obj = jQuery(this), value, newValue;
77
+ // Check
78
+ if ( !obj.length ) {
79
+ return obj;
80
+ }
81
+ // Calculate
82
+ value = obj.css(attr).toFloat();
83
+ newValue = Math.round((value||0)*0.8);
84
+ // Apply
85
+ if (value == newValue && newValue >0) { // when value is 2, won't increase
86
+ newValue--;
87
+ }
88
+ obj.css(attr,newValue);
89
+ // Chain
90
+ return obj;
91
+ }
92
+ });
93
+
94
+ // Create and register Image Plugin
95
+ return Plugin.create('image', {
96
+
97
+ languages: ['en', 'fr', 'de', 'ru', 'cz'],
98
+
99
+ defaultSettings: {
100
+ 'maxWidth': 1600,
101
+ 'minWidth': 3,
102
+ 'maxHeight': 1200,
103
+ 'minHeight': 3,
104
+ // This setting will correct manually values that are out of bounds
105
+ 'autoCorrectManualInput': true,
106
+ // This setting will define a fixed aspect ratio for all resize actions
107
+ 'fixedAspectRatio' : false,
108
+ // When enabled this setting will order the plugin to automatically resize images to given bounds
109
+ 'autoResize': false,
110
+ //Image manipulation options - ONLY in default config section
111
+ ui: {
112
+ oneTab : false, //Place all ui components within one tab
113
+ insert : true,
114
+ reset : true,
115
+ aspectRatioToggle: true, // Toggle button for the aspect ratio
116
+ align : true, // Menu elements to show/hide in menu
117
+ resize : true, // Resize buttons
118
+ meta : true,
119
+ margin : true,
120
+ crop : true,
121
+ resizable : true, // Resizable ui-drag image
122
+ handles : 'ne, se, sw, nw'
123
+ },
124
+
125
+ /**
126
+ * Crop callback is triggered after the user clicked accept to accept his crop
127
+ * @param image jquery image object reference
128
+ * @param props cropping properties
129
+ */
130
+ onCropped: function ($image, props) {
131
+ Aloha.Log.info('Default onCropped invoked', $image, props);
132
+ },
133
+
134
+ /**
135
+ * Reset callback is triggered before the internal reset procedure is applied
136
+ * if this function returns true, then the reset has been handled by the callback
137
+ * which means that no other reset will be applied
138
+ * if false is returned the internal reset procedure will be applied
139
+ * @param image jquery image object reference
140
+ * @return true if a reset has been applied, false otherwise
141
+ */
142
+ onReset: function ($image) {
143
+ Aloha.Log.info('Default onReset invoked', $image);
144
+ return false;
145
+ },
146
+
147
+ /**
148
+ * Example callback method which gets called while the resize process is beeing executed.
149
+ */
150
+ onResize: function ($image) {
151
+ Aloha.Log.info('Default onResize invoked', $image);
152
+ },
153
+
154
+ /**
155
+ * Resize callback is triggered after the internal resize procedure is applied.
156
+ */
157
+ onResized: function ($image) {
158
+ Aloha.Log.info('Default onResized invoked', $image);
159
+ }
160
+ },
161
+
162
+ /**
163
+ * Internal callback hook which gets invoked when cropping has been finished
164
+ */
165
+ _onCropped: function ($image, props) {
166
+ $('#' + this.imgResizeHeightField.id).val($image.height());
167
+ $('#' + this.imgResizeWidthField.id).val($image.width());
168
+
169
+
170
+ $('body').trigger('aloha-image-cropped', [$image, props]);
171
+
172
+ // Call the custom onCropped function
173
+ this.onCropped($image, props);
174
+ },
175
+
176
+ /**
177
+ * Internal callback hook which gets invoked when resetting images
178
+ */
179
+ _onReset: function ($image) {
180
+
181
+ $('#' + this.imgResizeHeightField.id).val($image.height());
182
+ $('#' + this.imgResizeWidthField.id).val($image.width());
183
+
184
+ // No default behaviour defined besides event triggering
185
+ $('body').trigger('aloha-image-reset', $image);
186
+
187
+ // Call the custom resize function
188
+ return this.onReset($image);
189
+ },
190
+
191
+ /**
192
+ * Internal callback hook which gets invoked while the image is beeing resized
193
+ */
194
+ _onResize: function ($image) {
195
+
196
+ $('#' + this.imgResizeHeightField.id).val($image.height());
197
+ $('#' + this.imgResizeWidthField.id).val($image.width());
198
+
199
+ // No default behaviour defined besides event triggering
200
+ $('body').trigger('aloha-image-resize', $image);
201
+
202
+ // Call the custom resize function
203
+ this.onResize($image);
204
+ },
205
+
206
+ /**
207
+ * Internal callback hook which gets invoked when the current resizing action has stopped
208
+ */
209
+ _onResized: function ($image) {
210
+
211
+ $('#' + this.imgResizeHeightField.id).val($image.height());
212
+ $('#' + this.imgResizeWidthField.id).val($image.width());
213
+
214
+ $('body').trigger('aloha-image-resized', $image);
215
+
216
+ // Call the custom resize function
217
+ this.onResized($image);
218
+ },
219
+
220
+ /**
221
+ * The image that is currently edited
222
+ */
223
+ imageObj: null,
224
+
225
+ /**
226
+ * The Jcrop API reference
227
+ * this is needed to be able to destroy the cropping frame later on
228
+ * the variable is linked to the api object whilst cropping, or set to null otherwise
229
+ * strange, but done as documented http://deepliquid.com/content/Jcrop_API.html
230
+ */
231
+ jcAPI: null,
232
+
233
+
234
+ /**
235
+ * State variable for the aspect ratio toggle feature
236
+ */
237
+ keepAspectRatio: false,
238
+
239
+ /**
240
+ * Variable that will hold the start aspect ratio. This ratio will be used once starResize will be called.
241
+ */
242
+ startAspectRatio: false,
243
+
244
+ /**
245
+ * This will contain an image's original properties to be able to undo previous settings
246
+ *
247
+ * when an image is clicked for the first time, a new object will be added to the array
248
+ * {
249
+ * obj : [the image object reference],
250
+ * src : [the original src url],
251
+ * width : [initial width],
252
+ * height : [initial height]
253
+ * }
254
+ *
255
+ * when an image is clicked the second time, the array will be checked for the image object
256
+ * referenct, to prevent for double entries
257
+ */
258
+ restoreProps: [],
259
+
260
+ objectTypeFilter: [],
261
+
262
+ /**
263
+ * Plugin initialization method
264
+ */
265
+ init: function() {
266
+
267
+ var that = this;
268
+
269
+ var imagePluginUrl = Aloha.getPluginUrl('image');
270
+
271
+ // Extend the default settings with the custom ones (done by default)
272
+ this.startAspectRatio = this.settings.fixedAspectRatio;
273
+ this.config = this.defaultSettings;
274
+ this.settings = jQuery.extend(true, this.defaultSettings, this.settings);
275
+
276
+ that.initializeButtons();
277
+ that.bindInteractions();
278
+ that.subscribeEvents();
279
+
280
+ },
281
+
282
+ /**
283
+ * Create buttons
284
+ */
285
+ initializeButtons: function() {
286
+
287
+ var that = this,
288
+ tabInsert = i18nCore.t('floatingmenu.tab.insert'),
289
+ tabImage = i18n.t('floatingmenu.tab.img'),
290
+ tabFormatting = i18n.t('floatingmenu.tab.formatting'),
291
+ tabCrop = i18n.t('floatingmenu.tab.crop'),
292
+ tabResize = i18n.t('floatingmenu.tab.resize');
293
+
294
+ FloatingMenu.createScope(this.name, 'Aloha.empty');
295
+
296
+ if (this.settings.ui.insert) {
297
+ var tabId = this.settings.ui.oneTab ? tabImage : tabInsert;
298
+ that._addUIInsertButton(tabId);
299
+ }
300
+
301
+ if (this.settings.ui.meta) {
302
+ var tabId = this.settings.ui.oneTab ? tabImage : tabImage;
303
+ that._addUIMetaButtons(tabId);
304
+ }
305
+
306
+ if (this.settings.ui.reset) {
307
+ var tabId = this.settings.ui.reset ? tabImage : tabImage;
308
+ that._addUIResetButton(tabId);
309
+ }
310
+
311
+ if (this.settings.ui.align) {
312
+ var tabId = this.settings.ui.oneTab ? tabImage : tabFormatting;
313
+ that._addUIAlignButtons(tabId);
314
+ }
315
+
316
+ if (this.settings.ui.margin) {
317
+ var tabId = this.settings.ui.oneTab ? tabImage : tabFormatting;
318
+ that._addUIMarginButtons(tabId);
319
+ }
320
+
321
+ if (this.settings.ui.crop) {
322
+ var tabId = this.settings.ui.oneTab ? tabImage : tabCrop;
323
+ that._addUICropButtons(tabId);
324
+ }
325
+
326
+ if (this.settings.ui.resize) {
327
+ var tabId = this.settings.ui.oneTab ? tabImage : tabResize;
328
+ that._addUIResizeButtons(tabId);
329
+ }
330
+
331
+ if (this.settings.ui.aspectRatioToggle) {
332
+ var tabId = this.settings.ui.oneTab ? tabImage : tabResize;
333
+ that.__addUIAspectRatioToggleButton(tabId);
334
+ }
335
+
336
+ // TODO fix the function and reenable this button
337
+ //that._addNaturalSizeButton();
338
+ },
339
+
340
+
341
+ /**
342
+ * Adds the aspect ratio toggle button to the floating menu
343
+ */
344
+ __addUIAspectRatioToggleButton: function(tabId) {
345
+ var that = this;
346
+ var toggleButton = new Aloha.ui.Button({
347
+ 'size' : 'small',
348
+ 'tooltip' : i18n.t('button.toggle.tooltip'),
349
+ 'toggle' : true,
350
+ 'iconClass' : 'cnr-ratio',
351
+ 'onclick' : function (btn, event) {
352
+ that.toggleKeepAspectRatio();
353
+ }
354
+ });
355
+
356
+
357
+ // If the setting has been set to a number or false we need to activate the
358
+ // toggle button to indicate that the aspect ratio will be preserved.
359
+ if (this.settings.fixedAspectRatio != false) {
360
+ toggleButton.pressed = true;
361
+ this.keepAspectRatio = true;
362
+ }
363
+
364
+ FloatingMenu.addButton(
365
+ that.name,
366
+ toggleButton,
367
+ tabId,
368
+ 20
369
+ );
370
+
371
+
372
+ },
373
+
374
+
375
+ /**
376
+ * Adds the reset button to the floating menu for the given tab
377
+ */
378
+ _addUIResetButton: function(tabId) {
379
+ var that = this;
380
+ // Reset button
381
+ var resetButton = new Aloha.ui.Button({
382
+ 'size' : 'small',
383
+ 'tooltip' : i18n.t('Reset'),
384
+ 'toggle' : false,
385
+ 'iconClass' : 'cnr-reset',
386
+ 'onclick' : function (btn, event) {
387
+ that.reset();
388
+ }
389
+ });
390
+
391
+ FloatingMenu.addButton(
392
+ that.name,
393
+ resetButton,
394
+ tabId,
395
+ 2
396
+ );
397
+ },
398
+
399
+ /**
400
+ * Adds the insert button to the floating menu
401
+ */
402
+ _addUIInsertButton: function(tabId) {
403
+ var that = this;
404
+ this.insertImgButton = new Aloha.ui.Button({
405
+ 'name' : 'insertimage',
406
+ 'iconClass': 'aloha-button aloha-image-insert',
407
+ 'size' : 'small',
408
+ 'onclick' : function () { that.insertImg(); },
409
+ 'tooltip' : i18n.t('button.addimg.tooltip'),
410
+ 'toggle' : false
411
+ });
412
+
413
+ FloatingMenu.addButton(
414
+ 'Aloha.continuoustext',
415
+ this.insertImgButton,
416
+ tabId,
417
+ 1
418
+ );
419
+ },
420
+
421
+ /**
422
+ * Adds the ui meta fields (search, title) to the floating menu.
423
+ */
424
+ _addUIMetaButtons: function(tabId) {
425
+ var that = this;
426
+ var imgSrcLabel = new Aloha.ui.Button({
427
+ 'label': i18n.t('field.img.src.label'),
428
+ 'tooltip': i18n.t('field.img.src.tooltip'),
429
+ 'size': 'small'
430
+ });
431
+ this.imgSrcField = new Aloha.ui.AttributeField({'name' : 'imgsrc'});
432
+ this.imgSrcField.setObjectTypeFilter( this.objectTypeFilter );
433
+
434
+ // add the title field for images
435
+ var imgTitleLabel = new Aloha.ui.Button({
436
+ 'label': i18n.t('field.img.title.label'),
437
+ 'tooltip': i18n.t('field.img.title.tooltip'),
438
+ 'size': 'small'
439
+ });
440
+
441
+ this.imgTitleField = new Aloha.ui.AttributeField();
442
+ this.imgTitleField.setObjectTypeFilter();
443
+ FloatingMenu.addButton(
444
+ this.name,
445
+ this.imgSrcField,
446
+ tabId,
447
+ 1
448
+ );
449
+
450
+ },
451
+
452
+ /**
453
+ * Adds the ui align buttons to the floating menu
454
+ */
455
+ _addUIAlignButtons: function(tabId) {
456
+ var that = this;
457
+
458
+ var alignLeftButton = new Aloha.ui.Button({
459
+ 'iconClass': 'aloha-img aloha-image-align-left',
460
+ 'size': 'small',
461
+ 'onclick' : function() {
462
+ var el = jQuery(that.findImgMarkup());
463
+ el.add(el.parent()).css('float', 'left');
464
+ },
465
+ 'tooltip': i18n.t('button.img.align.left.tooltip')
466
+ });
467
+
468
+ FloatingMenu.addButton(
469
+ that.name,
470
+ alignLeftButton,
471
+ tabId,
472
+ 1
473
+ );
474
+
475
+ var alignRightButton = new Aloha.ui.Button({
476
+ 'iconClass': 'aloha-img aloha-image-align-right',
477
+ 'size': 'small',
478
+ 'onclick' : function() {
479
+ var el = jQuery(that.findImgMarkup());
480
+ el.add(el.parent()).css('float', 'right');
481
+ },
482
+ 'tooltip': i18n.t('button.img.align.right.tooltip')
483
+ });
484
+
485
+ FloatingMenu.addButton(
486
+ that.name,
487
+ alignRightButton,
488
+ tabId,
489
+ 1
490
+ );
491
+
492
+ var alignNoneButton = new Aloha.ui.Button({
493
+ 'iconClass': 'aloha-img aloha-image-align-none',
494
+ 'size': 'small',
495
+ 'onclick' : function() {
496
+ var el = jQuery(that.findImgMarkup());
497
+ el.add(el.parent()).css({
498
+ 'float': 'none',
499
+ display: 'inline-block'
500
+ });
501
+ },
502
+ 'tooltip': i18n.t('button.img.align.none.tooltip')
503
+ });
504
+
505
+ FloatingMenu.addButton(
506
+ that.name,
507
+ alignNoneButton,
508
+ tabId,
509
+ 1
510
+ );
511
+
512
+ },
513
+
514
+ /**
515
+ * Adds the ui margin buttons to the floating menu
516
+ */
517
+ _addUIMarginButtons: function(tabId) {
518
+ var that = this;
519
+ var incPadding = new Aloha.ui.Button({
520
+ iconClass: 'aloha-img aloha-image-padding-increase',
521
+ toggle: false,
522
+ size: 'small',
523
+ onclick: function() {
524
+ jQuery(that.findImgMarkup()).increase('padding');
525
+ },
526
+ tooltip: i18n.t('padding.increase')
527
+ });
528
+ FloatingMenu.addButton(
529
+ that.name,
530
+ incPadding,
531
+ tabId,
532
+ 2
533
+ );
534
+
535
+ var decPadding = new Aloha.ui.Button({
536
+ iconClass: 'aloha-img aloha-image-padding-decrease',
537
+ toggle: false,
538
+ size: 'small',
539
+ onclick: function() {
540
+ jQuery(that.findImgMarkup()).decrease('padding');
541
+ },
542
+ tooltip: i18n.t('padding.decrease')
543
+ });
544
+ FloatingMenu.addButton(
545
+ that.name,
546
+ decPadding,
547
+ tabId,
548
+ 2
549
+ );
550
+ },
551
+
552
+ /**
553
+ * Adds the crop buttons to the floating menu
554
+ */
555
+ _addUICropButtons: function (tabId) {
556
+ var that = this;
557
+
558
+ FloatingMenu.createScope('Aloha.img', ['Aloha.global']);
559
+
560
+ this.cropButton = new Aloha.ui.Button({
561
+ 'size' : 'small',
562
+ 'tooltip' : i18n.t('Crop'),
563
+ 'toggle' : true,
564
+ 'iconClass' : 'cnr-crop',
565
+ 'onclick' : function (btn, event) {
566
+ if (btn.pressed) {
567
+ that.crop();
568
+ } else {
569
+ that.endCrop();
570
+ }
571
+ }
572
+ });
573
+
574
+ FloatingMenu.addButton(
575
+ this.name,
576
+ this.cropButton,
577
+ tabId,
578
+ 3
579
+ );
580
+
581
+ },
582
+
583
+ /**
584
+ * Adds the resize buttons to the floating menu
585
+ */
586
+ _addUIResizeButtons: function (tabId) {
587
+ var that = this;
588
+
589
+ // Manual resize fields
590
+ this.imgResizeHeightField = new Aloha.ui.AttributeField();
591
+ this.imgResizeHeightField.maxValue = that.settings.maxHeight;
592
+ this.imgResizeHeightField.minValue = that.settings.minHeight;
593
+
594
+ this.imgResizeWidthField = new Aloha.ui.AttributeField();
595
+ this.imgResizeWidthField.maxValue = that.settings.maxWidth;
596
+ this.imgResizeWidthField.minValue = that.settings.minWidth;
597
+
598
+ this.imgResizeWidthField.width = 50;
599
+ this.imgResizeHeightField.width = 50;
600
+
601
+ var widthLabel = new Aloha.ui.Button({
602
+ 'label': i18n.t('width'),
603
+ 'tooltip': i18n.t('width'),
604
+ 'size': 'small'
605
+ });
606
+
607
+ FloatingMenu.addButton(
608
+ this.name,
609
+ widthLabel,
610
+ tabId,
611
+ 30
612
+ );
613
+
614
+ FloatingMenu.addButton(
615
+ this.name,
616
+ this.imgResizeWidthField,
617
+ tabId,
618
+ 40
619
+ );
620
+
621
+
622
+ var heightLabel = new Aloha.ui.Button({
623
+ 'label': i18n.t('height'),
624
+ 'tooltip': i18n.t('height'),
625
+ 'size': 'small'
626
+ });
627
+
628
+ FloatingMenu.addButton(
629
+ this.name,
630
+ heightLabel,
631
+ tabId,
632
+ 50
633
+ );
634
+
635
+ FloatingMenu.addButton(
636
+ this.name,
637
+ this.imgResizeHeightField,
638
+ tabId,
639
+ 60
640
+ );
641
+
642
+
643
+ },
644
+
645
+ /**
646
+ * Adds the natural size button to the floating menu
647
+ */
648
+ _addNaturalSizeButton: function () {
649
+ var that = this;
650
+ var naturalSize = new Aloha.ui.Button({
651
+ iconClass: 'aloha-img aloha-image-size-natural',
652
+ size: 'small',
653
+ toggle: false,
654
+ onclick: function() {
655
+ var img = new Image();
656
+ img.onload = function() {
657
+ var myimage = that.findImgMarkup();
658
+ if (that.settings.ui.resizable) {
659
+ that.endResize();
660
+ }
661
+ jQuery(myimage).css({
662
+ 'width': img.width + 'px',
663
+ 'height': img.height + 'px',
664
+ 'max-width': '',
665
+ 'max-height': ''
666
+ });
667
+ if (that.settings.ui.resizable) {
668
+ that.resize();
669
+ }
670
+ };
671
+ img.src = that.findImgMarkup().src;
672
+
673
+ },
674
+ tooltip: i18n.t('size.natural')
675
+ });
676
+ FloatingMenu.addButton(
677
+ this.name,
678
+ naturalSize,
679
+ tabResize,
680
+ 2
681
+ );
682
+ },
683
+
684
+ /**
685
+ * Bind plugin interactions
686
+ */
687
+ bindInteractions: function () {
688
+ var that = this;
689
+
690
+ if (this.settings.ui.resizable) {
691
+ try {
692
+ // this will disable mozillas image resizing facilities
693
+ document.execCommand( 'enableObjectResizing', false, false );
694
+ } catch (e) {
695
+ Aloha.Log.error( e, 'Could not disable enableObjectResizing' );
696
+ // this is just for internet explorer, who will not support disabling enableObjectResizing
697
+ }
698
+ }
699
+
700
+ if (this.settings.ui.meta) {
701
+ // update image object when src changes
702
+ this.imgSrcField.addListener('keyup', function(obj, event) {
703
+ that.srcChange();
704
+ });
705
+
706
+ this.imgSrcField.addListener('blur', function(obj, event) {
707
+ // TODO remove image or do something usefull if the user leaves the
708
+ // image without defining a valid image src.
709
+ var img = jQuery(obj.getTargetObject());
710
+ if ( img.attr('src') === '' ) {
711
+ img.remove();
712
+ } // image removal when src field is blank
713
+ });
714
+ }
715
+
716
+ // Override the default method by using the given one
717
+ if (this.settings.onCropped && typeof this.settings.onCropped === "function") {
718
+ this.onCropped = this.settings.onCropped;
719
+ }
720
+
721
+ // Override the default method by using the given one
722
+ if (this.settings.onReset && typeof this.settings.onReset === "function") {
723
+ this.onReset = this.settings.onReset;
724
+ }
725
+
726
+ // Override the default method by using the given one
727
+ if (this.settings.onResized && typeof this.settings.onResized === "function") {
728
+ this.onResized = this.settings.onResized;
729
+ }
730
+
731
+ // Override the default method by using the given one
732
+ if (this.settings.onResize && typeof this.settings.onResize === "function") {
733
+ this.onResize = this.settings.onResize;
734
+ }
735
+
736
+ },
737
+
738
+ /**
739
+ * Subscribe to Aloha events and DragAndDropPlugin Event
740
+ */
741
+ subscribeEvents: function() {
742
+ var that = this;
743
+ var config = this.settings;
744
+
745
+ jQuery('img').filter(config.globalselector).unbind();
746
+ jQuery('img').filter(config.globalselector).click(function(event) {
747
+ that.clickImage(event);
748
+ });
749
+
750
+ Aloha.bind('aloha-drop-files-in-editable', function(event, data) {
751
+ var img, len = data.filesObjs.length, fileObj, config;
752
+
753
+ while (--len >= 0) {
754
+ fileObj = data.filesObjs[len];
755
+ if (fileObj.file.type.match(/image\//)) {
756
+ config = that.getEditableConfig(data.editable);
757
+ // Prepare
758
+ img = jQuery('<img/>');
759
+ img.css({
760
+ "max-width": that.maxWidth,
761
+ "max-height": that.maxHeight
762
+ });
763
+ img.attr('id',fileObj.id);
764
+ if (typeof fileObj.src === 'undefined') {
765
+ img.attr('src', fileObj.data );
766
+ //fileObj.src = fileObj.data ;
767
+ } else {
768
+ img.attr('src',fileObj.src );
769
+ }
770
+ GENTICS.Utils.Dom.insertIntoDOM(img, data.range, jQuery(Aloha.activeEditable.obj));
771
+ }
772
+ }
773
+
774
+ });
775
+
776
+ /*
777
+ * Add the event handler for selection change
778
+ */
779
+ Aloha.bind('aloha-selection-changed', function(event, rangeObject, originalEvent) {
780
+ var config, foundMarkup;
781
+ if (originalEvent && originalEvent.target) {
782
+ // Check if the element is currently beeing resized
783
+ if (that.settings.ui.resizable && !jQuery(originalEvent.target).hasClass('ui-resizable-handle')) {
784
+ that.endResize();
785
+ }
786
+ }
787
+
788
+ if (Aloha.activeEditable !== null) {
789
+ foundMarkup = that.findImgMarkup( rangeObject );
790
+ //var config = that.getEditableConfig(Aloha.activeEditable.obj);
791
+ config = that.getEditableConfig(Aloha.activeEditable.obj);
792
+
793
+ // FIXME (Did)
794
+ if (that.settings.ui.insert)
795
+ if (typeof config !== 'undefined' ) {
796
+ that.insertImgButton.show();
797
+ } else {
798
+ that.insertImgButton.hide();
799
+ return;
800
+ }
801
+
802
+ // Enable image specific ui components if the element is an image
803
+ if (foundMarkup) {
804
+ that.insertImgButton.hide();
805
+ FloatingMenu.setScope(that.name);
806
+ if (that.settings.ui.meta) {
807
+ that.imgSrcField.setTargetObject(foundMarkup, 'src');
808
+ that.imgTitleField.setTargetObject(foundMarkup, 'title');
809
+ }
810
+ that.imgSrcField.focus();
811
+ FloatingMenu.activateTabOfButton('imgsrc');
812
+ } else {
813
+ if (that.settings.ui.meta) {
814
+ that.imgSrcField.setTargetObject(null);
815
+ }
816
+ }
817
+ // TODO this should not be necessary here!
818
+ FloatingMenu.doLayout();
819
+ }
820
+
821
+ });
822
+
823
+ Aloha.bind('aloha-editable-created', function( event, editable) {
824
+
825
+ try {
826
+ // this will disable mozillas image resizing facilities
827
+ document.execCommand( 'enableObjectResizing', false, false);
828
+ } catch (e) {
829
+ Aloha.Log.error( e, 'Could not disable enableObjectResizing');
830
+ // this is just for others, who will not support disabling enableObjectResizing
831
+ }
832
+
833
+ // Inital click on images will be handled here
834
+ // editable.obj.find('img').attr('_moz_resizing', false);
835
+ // editable.obj.find('img').contentEditable(false);
836
+ editable.obj.delegate( 'img', 'mouseup', function (event) {
837
+ that.clickImage(event);
838
+ event.stopPropagation();
839
+ });
840
+ });
841
+
842
+ that._subscribeToResizeFieldEvents();
843
+
844
+ },
845
+
846
+ /**
847
+ * Automatically resize the image to fit into defined bounds.
848
+ */
849
+ autoResize: function() {
850
+ var that = this;
851
+
852
+ var width = that.imageObj.width();
853
+ var height = that.imageObj.height();
854
+
855
+ // Only normalize the field values when the image exeeds the definded bounds
856
+ if (width < that.settings.minWidth || width > that.settings.maxWidth || height < that.settings.minHeight || height > that.settings.maxHeight) {
857
+ that._setNormalizedFieldValues('width');
858
+ that.setSizeByFieldValue();
859
+ return true;
860
+ } else {
861
+ return false;
862
+ }
863
+ },
864
+
865
+ /**
866
+ * Toggle the keep aspect ratio functionallity
867
+ */
868
+ toggleKeepAspectRatio: function() {
869
+
870
+ this.keepAspectRatio = !this.keepAspectRatio;
871
+
872
+ this.endResize();
873
+ if (!this.keepAspectRatio) {
874
+ this.startAspectRatio = false;
875
+ } else {
876
+ // If no fixed aspect ratio was given we will calculate a new start
877
+ // aspect ratio that will be used for the next starResize action.
878
+ if ( typeof this.settings.fixedAspectRatio !== 'number' ) {
879
+ var currentRatio = this.imageObj.width() / this.imageObj.height();
880
+ this.startAspectRatio = currentRatio;
881
+ } else {
882
+ this.startAspectRatio = this.settings.fixedAspectRatio;
883
+ }
884
+ }
885
+ this.startResize();
886
+ },
887
+
888
+ /**
889
+ * Bind interaction events that are invoked on the resize fields
890
+ */
891
+ _subscribeToResizeFieldEvents: function() {
892
+ var that = this;
893
+
894
+ /**
895
+ * Helper function that will update the fields
896
+ */
897
+ function updateField( $field, delta, maxValue, minValue ) {
898
+
899
+ if ( typeof minValue === 'undefined' ) {
900
+ minValue = 0;
901
+ }
902
+
903
+ if ( typeof maxValue === 'undefined' ) {
904
+ maxValue = 8000;
905
+ }
906
+
907
+ // If the current value of the field can't be parsed we don't update it
908
+ var oldValue = parseInt( $field.val() );
909
+ if ( isNaN(oldValue) ) {
910
+ $field.css( 'background-color', 'red' );
911
+ return false;
912
+ }
913
+
914
+ var newValue = oldValue + delta;
915
+ // Exit if the newValue is above the maxValue limit (only if the user tries to increment)
916
+ if (delta>=0 && newValue > maxValue) {
917
+
918
+ // Auto correct out of bounds values
919
+ if (that.settings.autoCorrectManualInput) {
920
+ $field.val(maxValue);
921
+ return true;
922
+ } else {
923
+ $field.css('background-color','red');
924
+ return false;
925
+ }
926
+ // Exit if the newValue is below the minValue (only if the user tries to decrement)
927
+ } else if (delta<=0 && newValue<minValue) {
928
+
929
+ // Auto correct out of bounds values
930
+ if (that.settings.autoCorrectManualInput) {
931
+ $field.val(minValue);
932
+ return true;
933
+ } else {
934
+ $field.css('background-color','red');
935
+ return false;
936
+ }
937
+ } else {
938
+ $field.css('background-color','');
939
+ }
940
+ $field.val(oldValue + delta);
941
+ return true;
942
+ };
943
+
944
+ /**
945
+ * Handle the keyup event on the field
946
+ */
947
+ function handleKeyUpEventOnField(e) {
948
+
949
+ // Load the max/min from the data properties of this event
950
+ var minValue = e.data.minValue;
951
+ var maxValue = e.data.maxValue;
952
+ var fieldName = e.data.fieldName;
953
+
954
+ // Allow backspace and delete
955
+ if (e.keyCode == 8 || e.keyCode == 46) {
956
+ if($(this).val() >= minValue) {
957
+
958
+ // Check if we are currently in cropping mode
959
+ if(typeof that.jcAPI !== 'undefined' && that.jcAPI != null) {
960
+ that.setCropAreaByFieldValue();
961
+ } else {
962
+ // 1. Normalize the size
963
+ that._setNormalizedFieldValues(fieldName);
964
+ // 2. Set the final size to the image
965
+ that.setSizeByFieldValue();
966
+ }
967
+ }
968
+ // 0-9 keys
969
+ } else if (e.keyCode <= 57 && e.keyCode >= 48 || e.keyCode <= 105 && e.keyCode >= 96 ) {
970
+ if($(this).val() >= minValue) {
971
+
972
+ // Check if we are currently in cropping mode
973
+ if(typeof that.jcAPI !== 'undefined' && that.jcAPI != null) {
974
+ that.setCropAreaByFieldValue();
975
+ } else {
976
+ // 1. Normalize the size
977
+ that._setNormalizedFieldValues(fieldName);
978
+ // 2. Set the final size to the image
979
+ that.setSizeByFieldValue();
980
+ }
981
+ }
982
+ } else {
983
+ var delta = 0;
984
+ if (e.keyCode == 38 || e.keyCode == 107) {
985
+ delta = +1;
986
+ } else if (e.keyCode == 40 || e.keyCode == 109) {
987
+ delta = -1;
988
+ }
989
+ // Handle key combinations
990
+ if ( e.shiftKey || e.metaKey || e.ctrlKey ) {
991
+ delta = delta * 10;
992
+ }
993
+
994
+ // Only resize when field values are ok
995
+ if(updateField($(this), delta, maxValue, minValue)) {
996
+ // Check if we are currently in cropping mode
997
+ if(typeof that.jcAPI !== 'undefined' && that.jcAPI != null) {
998
+ that.setCropAreaByFieldValue();
999
+ } else {
1000
+ // 1. Normalize the size
1001
+ that._setNormalizedFieldValues(fieldName);
1002
+ // 2. Set the final size to the image
1003
+ that.setSizeByFieldValue();
1004
+ }
1005
+ }
1006
+ }
1007
+
1008
+ e.preventDefault();
1009
+ return false;
1010
+ };
1011
+
1012
+ /**
1013
+ * Handle the mouse wheel event on the field
1014
+ */
1015
+ function handleMouseWheelEventOnField(e, delta) {
1016
+ var minValue = e.data.minValue;
1017
+ var maxValue = e.data.maxValue;
1018
+ var fieldName = e.data.fieldName;
1019
+
1020
+ // Handle key combinations
1021
+ if ( e.shiftKey || e.metaKey || e.ctrlKey ) {
1022
+ delta = delta * 10;
1023
+ }
1024
+
1025
+ // Only resize when field values are ok
1026
+ if(updateField($(this), delta, maxValue, minValue)) {
1027
+
1028
+ // Check if we are currently in cropping mode
1029
+ if(typeof that.jcAPI !== 'undefined' && that.jcAPI != null) {
1030
+ that.setCropAreaByFieldValue();
1031
+ } else {
1032
+ // 1. Normalize the size
1033
+ that._setNormalizedFieldValues(fieldName);
1034
+ // 2. Set the final size to the image
1035
+ that.setSizeByFieldValue();
1036
+ }
1037
+ }
1038
+ return false;
1039
+ };
1040
+
1041
+ /**
1042
+ * Handle mousewheel,keyup actions on both fields
1043
+ */
1044
+ var $heightField = $('#' + that.imgResizeHeightField.id );
1045
+ var heightEventData = {fieldName: 'height', maxValue: that.imgResizeHeightField.maxValue, minValue: that.imgResizeHeightField.minValue };
1046
+ $heightField.live('keyup', heightEventData, handleKeyUpEventOnField);
1047
+ $heightField.live('mousewheel', heightEventData, handleMouseWheelEventOnField);
1048
+
1049
+ var $widthField = $('#' + that.imgResizeWidthField.id );
1050
+ var widthEventData = {fieldName: 'width', maxValue: that.imgResizeWidthField.maxValue , minValue: that.imgResizeWidthField.minValue };
1051
+ $widthField.live('keyup',widthEventData , handleKeyUpEventOnField);
1052
+ $widthField.live('mousewheel', widthEventData, handleMouseWheelEventOnField);
1053
+
1054
+ },
1055
+
1056
+
1057
+ /**
1058
+ * This helper function will keep the aspect ratio for the field with the given name.
1059
+ */
1060
+ _setNormalizedFieldValues: function(primaryFieldName) {
1061
+
1062
+ var that = this;
1063
+ var widthField = jQuery("#" + that.imgResizeWidthField.id);
1064
+ var heightField = jQuery("#" + that.imgResizeHeightField.id);
1065
+ var width = widthField.val();
1066
+ var height = heightField.val();
1067
+
1068
+ var size = that._normalizeSize(width, height, primaryFieldName);
1069
+
1070
+ widthField.val(size.width);
1071
+ heightField.val(size.height);
1072
+
1073
+ },
1074
+
1075
+ /**
1076
+ * Manually set the given size for the current image
1077
+ */
1078
+ setSize: function(width, height) {
1079
+
1080
+ var that = this;
1081
+ this.imageObj.width(width);
1082
+ this.imageObj.height(height);
1083
+ var $wrapper = this.imageObj.closest('.Aloha_Image_Resize');
1084
+ $wrapper.height(height);
1085
+ $wrapper.width(width);
1086
+
1087
+ this._onResize(this.imageObj);
1088
+ this._onResized(this.imageObj);
1089
+ },
1090
+
1091
+ /**
1092
+ * This method will handle the mouseUp event on images (eg. within editables).
1093
+ * It will if enabled activate the resizing action.
1094
+ */
1095
+ clickImage: function( e ) {
1096
+
1097
+ var that = this;
1098
+ that.imageObj = jQuery(e.target);
1099
+ var currentImage = that.imageObj;
1100
+
1101
+ FloatingMenu.setScope(that.name);
1102
+
1103
+ var editable = currentImage.closest('.aloha-editable');
1104
+
1105
+ // Disabling the content editable. This will disable the resizeHandles in internet explorer
1106
+ jQuery(editable).contentEditable(false);
1107
+
1108
+ //Store the current props of the image
1109
+ this.restoreProps.push({
1110
+ obj : e.srcElement,
1111
+ src : that.imageObj.attr('src'),
1112
+ width : that.imageObj.width(),
1113
+ height : that.imageObj.height()
1114
+ });
1115
+
1116
+ // Update the resize input fields with the new width and height
1117
+ $('#' + that.imgResizeHeightField.id).val(that.imageObj.height());
1118
+ $('#' + that.imgResizeWidthField.id).val(that.imageObj.width());
1119
+
1120
+
1121
+ if (this.settings.ui.resizable) {
1122
+ this.startResize();
1123
+ }
1124
+
1125
+
1126
+ if (this.settings.autoResize) {
1127
+ this.autoResize();
1128
+ }
1129
+
1130
+ },
1131
+
1132
+ /**
1133
+ * This method extracts determins if the range selection contains an image
1134
+ */
1135
+ findImgMarkup: function ( range ) {
1136
+
1137
+ var that = this;
1138
+ var config = this.config;
1139
+ var result, targetObj;
1140
+
1141
+ if ( typeof range === 'undefined' ) {
1142
+ range = Aloha.Selection.getRangeObject();
1143
+ }
1144
+
1145
+ targetObj = jQuery(range.startContainer);
1146
+
1147
+ try {
1148
+ if ( Aloha.activeEditable ) {
1149
+ if (( typeof range.startContainer !== 'undefined'
1150
+ && typeof range.startContainer.childNodes !== 'undefined'
1151
+ && typeof range.startOffset !== 'undefined'
1152
+ && typeof range.startContainer.childNodes[range.startOffset] !== 'undefined'
1153
+ && range.startContainer.childNodes[range.startOffset].nodeName.toLowerCase() === 'img'
1154
+ && range.startOffset+1 === range.endOffset) ||
1155
+ (targetObj.hasClass('Aloha_Image_Resize')))
1156
+ {
1157
+ result = targetObj.find('img')[0];
1158
+ if (! result.css) {
1159
+ result.css = '';
1160
+ }
1161
+
1162
+ if (! result.title) {
1163
+ result.title = '';
1164
+ }
1165
+
1166
+ if (! result.src) {
1167
+ result.src = '';
1168
+ }
1169
+ return result;
1170
+ }
1171
+ else {
1172
+ return null;
1173
+ }
1174
+ }
1175
+ } catch (e) {
1176
+ Aloha.Log.debug(e, "Error finding img markup.");
1177
+ }
1178
+ return null;
1179
+
1180
+ },
1181
+
1182
+
1183
+ /**
1184
+ * This helper function will calculate the new width and height while keeping
1185
+ * the aspect ratio when the keepAspectRatio flat is set to true. The primarySize
1186
+ * can be 'width' or 'height'. The function will first try to normalize the oposite size.
1187
+ */
1188
+ _normalizeSize: function(width, height, primarySize) {
1189
+
1190
+ var that = this;
1191
+ // Convert string values to numbers
1192
+ width = parseInt(width);
1193
+ height = parseInt(height);
1194
+
1195
+ /**
1196
+ * Inner function that calculates the new height by examining the width
1197
+ */
1198
+ function handleHeight(callHandleWidth) {
1199
+
1200
+ // Check whether the value is within bounds
1201
+ if (height > that.settings.maxHeight) {
1202
+
1203
+ // Throw a notification event
1204
+ var eventProps = { 'org': height, 'new': that.settings.maxHeight};
1205
+ $('body').trigger('aloha-image-resize-outofbounds', ["height", "max", eventProps]);
1206
+ height = that.settings.maxHeight;
1207
+
1208
+ } else if (height < that.settings.minHeight) {
1209
+
1210
+ // Throw a notification event
1211
+ var eventProps = { 'org': height, 'new': that.settings.minHeight};
1212
+ $('body').trigger('aloha-image-resize-outofbounds', ["height", "min", eventProps]);
1213
+ height = that.settings.minHeight;
1214
+ }
1215
+
1216
+ if (that.keepAspectRatio) {
1217
+ width = height * aspectRatio;
1218
+
1219
+ // We don't want to invoke handleWidth again. This would mess up our previously calculated width
1220
+ if (callHandleWidth) {
1221
+ handleWidth(false);
1222
+ }
1223
+ }
1224
+
1225
+
1226
+ }
1227
+
1228
+ /**
1229
+ * Inner function that calculates the new width by examining the width
1230
+ */
1231
+ function handleWidth(callHandleHeight) {
1232
+
1233
+ // Check whether the value is within bounds
1234
+ if (width > that.settings.maxWidth) {
1235
+
1236
+ // Throw a notification event
1237
+ var eventProps = { 'org': width, 'new': that.settings.maxWidth};
1238
+ $('body').trigger('aloha-image-resize-outofbounds', ["width", "max", eventProps]);
1239
+
1240
+ width = that.settings.maxWidth;
1241
+ } else if (width < that.settings.minWidth) {
1242
+
1243
+ // Throw a notification event
1244
+ var eventProps = { 'org': width, 'new': that.settings.minWidth};
1245
+ $('body').trigger('aloha-image-resize-outofbounds', ["width", "min", eventProps]);
1246
+
1247
+ width = that.settings.minWidth;
1248
+ }
1249
+
1250
+ // Calculate the new height
1251
+ if (that.keepAspectRatio) {
1252
+ height = width / aspectRatio;
1253
+
1254
+ // We don't want to invoke handleHeight again. This would mess up our previously calculated height
1255
+ if (callHandleHeight) {
1256
+ handleHeight(false);
1257
+ }
1258
+
1259
+ }
1260
+
1261
+ }
1262
+
1263
+ // Load the aspect ratio and use the 4:3 ratio as default value.
1264
+ var aspectRatio = 1.33333;
1265
+ if (typeof that.startAspectRatio === 'number') {
1266
+ aspectRatio = that.startAspectRatio;
1267
+ }
1268
+
1269
+ // Determin which size should be handled
1270
+ if (primarySize == 'width') {
1271
+ handleWidth(true);
1272
+ }
1273
+
1274
+ if (primarySize == 'height') {
1275
+ handleHeight(true);
1276
+ }
1277
+
1278
+ // Floor the values return them
1279
+ return {'width': Math.floor(width), 'height': Math.floor(height)};
1280
+ },
1281
+
1282
+
1283
+ /**
1284
+ * Helper function that will set the new image size using the field values
1285
+ */
1286
+ setSizeByFieldValue: function() {
1287
+ var that = this;
1288
+ var width = $('#' + that.imgResizeWidthField.id ).val();
1289
+ var height = $('#' + that.imgResizeHeightField.id ).val();
1290
+ that.setSize(width, height);
1291
+ },
1292
+
1293
+ /**
1294
+ * Helper function that will set the new crop area width and height using the field values
1295
+ */
1296
+ setCropAreaByFieldValue: function() {
1297
+ var that = this;
1298
+ var currentCropArea = that.jcAPI.tellSelect();
1299
+
1300
+ var width = $('#' + that.imgResizeWidthField.id ).val();
1301
+ width = parseInt(width);
1302
+ var height = $('#' + that.imgResizeHeightField.id ).val();
1303
+ height = parseInt(height);
1304
+
1305
+ var selection = [currentCropArea['x'], currentCropArea['y'], currentCropArea['x'] + width,currentCropArea['y'] + height];
1306
+ that.jcAPI.setSelect(selection);
1307
+ },
1308
+
1309
+ /**
1310
+ * This method will insert a new image dom element into the dom tree
1311
+ */
1312
+ insertImg: function() {
1313
+ var range = Aloha.Selection.getRangeObject(),
1314
+ config = this.getEditableConfig(Aloha.activeEditable.obj),
1315
+ imagePluginUrl = Aloha.getPluginUrl('image'),
1316
+ imagestyle, imagetag, newImg;
1317
+
1318
+ if ( range.isCollapsed() ) {
1319
+ // TODO I would suggest to call the srcChange method. So all image src
1320
+ // changes are on one single point.
1321
+ imagestyle = "max-width: " + config.maxWidth + "; max-height: " + config.maxHeight;
1322
+ imagetag = '<img style="'+ imagestyle + '" src="' + imagePluginUrl + '/img/blank.jpg" title="" />';
1323
+ newImg = jQuery(imagetag);
1324
+ // add the click selection handler
1325
+ //newImg.click( Aloha.Image.clickImage ); - Using delegate now
1326
+ GENTICS.Utils.Dom.insertIntoDOM(newImg, range, jQuery(Aloha.activeEditable.obj));
1327
+
1328
+ } else {
1329
+ Aloha.Log.error('img cannot markup a selection');
1330
+ // TODO the desired behavior could be me the selected content is
1331
+ // replaced by an image.
1332
+ // TODO it should be editor's choice, with an NON-Ext Dialog instead of alert
1333
+
1334
+ }
1335
+ },
1336
+
1337
+ srcChange: function () {
1338
+ // TODO the src changed. I suggest :
1339
+ // 1. set an loading image (I suggest set src base64 enc) to show the user
1340
+ // we are trying to load an image
1341
+ // 2. start a request to get the image
1342
+ // 3a. the image is ok change the src
1343
+ // 3b. the image is not availbable show an error.
1344
+ this.imageObj.attr('src', this.imgSrcField.getQueryValue() ); // (the img tag)
1345
+ // jQuery(img).attr('src', this.imgSrcField.getQueryValue() ); // (the query value in the inputfield)
1346
+ // this.imgSrcField.getItem(); // (optinal a selected resource item)
1347
+ // TODO additionally implement an srcChange Handler to let implementer
1348
+ // customize
1349
+ },
1350
+
1351
+ /**
1352
+ * Reposition the crop buttons below the crop area
1353
+ */
1354
+ positionCropButtons: function() {
1355
+
1356
+ var jt = jQuery('.jcrop-tracker:first'),
1357
+ off = jt.offset(),
1358
+ jtt = off.top,
1359
+ jtl = off.left,
1360
+ jth = jt.height(),
1361
+ jtw = jt.width();
1362
+
1363
+ var oldLeft = 0,
1364
+ oldTop = 0;
1365
+
1366
+ var btns = jQuery('#aloha-CropNResize-btns');
1367
+
1368
+ // Hack to hide the buttons when the user just clicked into the image
1369
+ if ( jtt == 0 && jtl == 0 ) {
1370
+ btns.hide();
1371
+ }
1372
+
1373
+ // move the icons to the bottom right side
1374
+ jtt = parseInt(jtt + jth + 3, 10);
1375
+ jtl = parseInt(jtl + (jtw/2)-(btns.width()/2)+10, 10);
1376
+
1377
+ // comparison to old values hinders flickering bug in FF
1378
+ if (oldLeft != jtl || oldTop != jtt) {
1379
+ btns.offset({top: jtt, left: jtl});
1380
+ }
1381
+
1382
+ oldLeft = jtl;
1383
+ oldTop = jtt;
1384
+ },
1385
+
1386
+ /**
1387
+ * Code imported from CropnResize Plugin
1388
+ *
1389
+ */
1390
+ initCropButtons: function() {
1391
+ var that = this,
1392
+ btns;
1393
+
1394
+ jQuery('body').append(
1395
+ '<div id="aloha-CropNResize-btns" display="none">' +
1396
+ '<button class="cnr-crop-apply" title="' + i18n.t('Accept') + '"></button>' +
1397
+ '<button class="cnr-crop-cancel" title="' + i18n.t('Cancel') + '"></button>' +
1398
+ '</div>'
1399
+ );
1400
+
1401
+ btns = jQuery('#aloha-CropNResize-btns');
1402
+
1403
+ btns.find('.cnr-crop-apply').click(function () {
1404
+ that.acceptCrop();
1405
+ });
1406
+
1407
+ btns.find('.cnr-crop-cancel').click(function () {
1408
+ that.endCrop();
1409
+ });
1410
+
1411
+ this.interval = setInterval(function () {
1412
+ that.positionCropButtons();
1413
+ }, 10);
1414
+ },
1415
+
1416
+ /**
1417
+ * Destroy crop confirm and cancel buttons
1418
+ */
1419
+ destroyCropButtons: function () {
1420
+ jQuery('#aloha-CropNResize-btns').remove();
1421
+ clearInterval(this.interval);
1422
+ },
1423
+
1424
+ /**
1425
+ * Helper function that will disable selectability of elements
1426
+ */
1427
+ _disableSelection: function (el) {
1428
+ el.find('*').attr('unselectable', 'on')
1429
+ .css({
1430
+ '-moz-user-select':'none',
1431
+ '-webkit-user-select':'none',
1432
+ 'user-select':'none'
1433
+ });
1434
+ /*
1435
+ .each(function() {
1436
+ this.onselectstart = function () { return false; };
1437
+ });
1438
+ */
1439
+
1440
+ },
1441
+
1442
+ /**
1443
+ * Initiate a crop action
1444
+ */
1445
+ crop: function () {
1446
+ var that = this;
1447
+ var config = this.config;
1448
+
1449
+ this.initCropButtons();
1450
+ if (this.settings.ui.resizable) {
1451
+ this.endResize();
1452
+ }
1453
+
1454
+ this.jcAPI = jQuery.Jcrop(this.imageObj, {
1455
+ onSelect : function () {
1456
+ that._onCropSelect();
1457
+ // ugly hack to keep scope :(
1458
+ setTimeout(function () {
1459
+ FloatingMenu.setScope(that.name);
1460
+ }, 10);
1461
+ }
1462
+ });
1463
+
1464
+ that._disableSelection($('.jcrop-holder'));
1465
+ that._disableSelection($('#imageContainer'));
1466
+ that._disableSelection($('#aloha-CropNResize-btns'));
1467
+ $('body').trigger('aloha-image-crop-start', [this.imageObj]);
1468
+ },
1469
+
1470
+ /**
1471
+ * Internal on crop select method
1472
+ */
1473
+ _onCropSelect: function() {
1474
+ var that = this;
1475
+
1476
+ jQuery('#aloha-CropNResize-btns').fadeIn('slow');
1477
+
1478
+ // Hide the crop buttons when the one of the handles is clicked
1479
+ jQuery('.jcrop-handle').mousedown(function() {
1480
+ jQuery('#aloha-CropNResize-btns').hide();
1481
+ });
1482
+
1483
+ jQuery('.jcrop-tracker').mousedown(function() {
1484
+ jQuery('#aloha-CropNResize-btns').hide();
1485
+ });
1486
+
1487
+ // Update the width and height field using the intiial active crop area values
1488
+ if(typeof that.jcAPI !== 'undefined' && that.jcAPI != null) {
1489
+
1490
+ that.positionCropButtons();
1491
+ var currentCropArea = that.jcAPI.tellSelect();
1492
+
1493
+ var widthField = jQuery("#" + that.imgResizeWidthField.id).val(currentCropArea['w']);
1494
+ var heightField = jQuery("#" + that.imgResizeHeightField.id).val(currentCropArea['h']);
1495
+ }
1496
+
1497
+ },
1498
+
1499
+
1500
+ /**
1501
+ * Terminates a crop
1502
+ */
1503
+ endCrop: function () {
1504
+ if ( this.jcAPI ) {
1505
+ this.jcAPI.destroy();
1506
+ this.jcAPI = null;
1507
+ }
1508
+
1509
+ this.destroyCropButtons();
1510
+ this.cropButton.extButton.toggle(false);
1511
+
1512
+ if ( this.settings.ui.resizable ) {
1513
+ this.startResize();
1514
+ }
1515
+
1516
+ if ( this.keepAspectRatio ) {
1517
+ var currentRatio = this.imageObj.width() / this.imageObj.height();
1518
+ this.startAspectRatio = currentRatio;
1519
+ }
1520
+
1521
+ $('body').trigger('aloha-image-crop-stop', [this.imageObj]);
1522
+ },
1523
+
1524
+ /**
1525
+ * Accept the current cropping area and apply the crop
1526
+ */
1527
+ acceptCrop: function () {
1528
+ this._onCropped ( this.imageObj, this.jcAPI.tellSelect() );
1529
+ this.endCrop ();
1530
+ },
1531
+
1532
+ /**
1533
+ * This method will activate the jquery-ui resize functionality for the current image
1534
+ */
1535
+ startResize: function () {
1536
+ var that = this;
1537
+ var currentImageObj = this.imageObj;
1538
+
1539
+ currentImageObj = this.imageObj.css({
1540
+ height : this.imageObj.height(),
1541
+ width : this.imageObj.width(),
1542
+ position : 'relative',
1543
+ 'max-height': '',
1544
+ 'max-width' : ''
1545
+ });
1546
+
1547
+ currentImageObj.resizable({
1548
+
1549
+ maxHeight : that.settings.maxHeight,
1550
+ minHeight : that.settings.minHeight,
1551
+ maxWidth : that.settings.maxWidth,
1552
+ minWidth : that.settings.minWidth,
1553
+ aspectRatio : that.startAspectRatio,
1554
+ handles: that.settings.handles,
1555
+ grid : that.settings.grid,
1556
+ resize: function(event, ui) {
1557
+ that._onResize(that.imageObj);
1558
+ },
1559
+ stop : function (event, ui) {
1560
+ that._onResized(that.imageObj);
1561
+
1562
+ // Workaround to finish cropping
1563
+ if (this.enableCrop) {
1564
+ setTimeout(function () {
1565
+ FloatingMenu.setScope(that.name);
1566
+ that.done(event);
1567
+ }, 10);
1568
+ }
1569
+ }
1570
+
1571
+ });
1572
+
1573
+ currentImageObj.css('display', 'inline-block');
1574
+
1575
+ // this will prevent the user from resizing an image
1576
+ // using IE's resize handles
1577
+ // however I could not manage to hide them completely
1578
+ jQuery('.ui-wrapper')
1579
+ .attr('contentEditable', false)
1580
+ .addClass('aloha-image-box-active Aloha_Image_Resize aloha')
1581
+ .css({
1582
+ position: 'relative',
1583
+ display: 'inline-block',
1584
+ 'float': that.imageObj.css('float')
1585
+ })
1586
+ .bind('resizestart', function (e) {
1587
+ e.preventDefault();
1588
+ })
1589
+ .bind('mouseup', function (e) {
1590
+ e.originalEvent.stopSelectionUpdate = true;
1591
+ });
1592
+ },
1593
+
1594
+ /**
1595
+ * This method will end resizing and toggle buttons accordingly and remove all markup that has been added for cropping
1596
+ */
1597
+ endResize: function () {
1598
+ // Find the nearest contenteditable and reenable it since resizing is finished
1599
+ if (this.imageObj) {
1600
+ var editable = this.imageObj.closest('.aloha-editable');
1601
+ jQuery(editable).contentEditable(true);
1602
+ }
1603
+
1604
+ if (this.imageObj) {
1605
+ this.imageObj
1606
+ .resizable('destroy')
1607
+ .css({
1608
+ top : 0,
1609
+ left : 0
1610
+ });
1611
+ }
1612
+ },
1613
+
1614
+ /**
1615
+ * Reset the image to it's original properties
1616
+ */
1617
+ reset: function() {
1618
+ if (this.settings.ui.crop) {
1619
+ this.endCrop();
1620
+ }
1621
+
1622
+ if (this.settings.ui.resizable) {
1623
+ this.endResize();
1624
+ }
1625
+
1626
+ if (this._onReset(this.imageObj)) {
1627
+ // the external reset procedure has already performed a reset, so there is no need to apply an internal reset
1628
+ return;
1629
+ }
1630
+
1631
+ for (var i=0;i<this.restoreProps.length;i++) {
1632
+ // restore from restoreProps if there is a match
1633
+ if (this.imageObj.get(0) === this.restoreProps[i].obj) {
1634
+ this.imageObj.attr('src', this.restoreProps[i].src);
1635
+ this.imageObj.width(this.restoreProps[i].width);
1636
+ this.imageObj.height(this.restoreProps[i].height);
1637
+ return;
1638
+ }
1639
+ }
1640
+ }
1641
+ });
1614
1642
 
1615
1643
  });