locomotive-aloha-rails 0.20.1.2 → 0.20.1.3

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -86,19 +86,22 @@ function( Aloha, Registry, Engine, Dom, ContentHandlerManager ) {
86
86
  }
87
87
 
88
88
  Engine.execCommand( commandId, showUi, value, range );
89
-
90
- // Read range after engine modification
91
- range = Aloha.getSelection().getRangeAt( 0 );
92
-
93
- // FIX: doCleanup should work with W3C range
94
- var startnode = range.commonAncestorContainer.parentNode;
95
- var rangeObject = new window.GENTICS.Utils.RangeObject();
96
- rangeObject.startContainer = range.startContainer;
97
- rangeObject.startOffset = range.startOffset;
98
- rangeObject.endContainer = range.endContainer;
99
- rangeObject.endOffset = range.endOffset;
100
- Dom.doCleanup({merge:true, removeempty: false}, rangeObject, startnode);
101
- rangeObject.select();
89
+
90
+ if ( Aloha.getSelection().getRangeCount() ) {
91
+ // Read range after engine modification
92
+ range = Aloha.getSelection().getRangeAt( 0 );
93
+
94
+ // FIX: doCleanup should work with W3C range
95
+ var startnode = range.commonAncestorContainer.parentNode;
96
+ var rangeObject = new window.GENTICS.Utils.RangeObject();
97
+ rangeObject.startContainer = range.startContainer;
98
+ rangeObject.startOffset = range.startOffset;
99
+ rangeObject.endContainer = range.endContainer;
100
+ rangeObject.endOffset = range.endOffset;
101
+ Dom.doCleanup({merge:true, removeempty: false}, rangeObject, startnode);
102
+ rangeObject.select();
103
+ }
104
+
102
105
  Aloha.trigger('aloha-command-executed', commandId);
103
106
  },
104
107
 
@@ -28,6 +28,12 @@ define(
28
28
  function ( jQuery, PluginManager ) {
29
29
 
30
30
 
31
+ // Aloha Editor does not support Internet Explorer 6. ExtJS style fixes for
32
+ // IE6 which are applied through the "ext-ie6" class cause visual bugs in
33
+ // IE9, and so we remove it so that IE6 fixes are not applied.
34
+ Aloha.ready(function() {
35
+ jQuery('.ext-ie6').removeClass('ext-ie6');
36
+ });
31
37
 
32
38
  //----------------------------------------
33
39
  // Private variables
@@ -227,6 +233,8 @@ function ( jQuery, PluginManager ) {
227
233
  * Fetches plugins the user wants to have loaded. Returns all plugins the user
228
234
  * has specified with the data-plugins property as array, with the bundle
229
235
  * name in front.
236
+ * It's also possible to use 'Aloha.settings.plugins.load' to define the plugins
237
+ * to load.
230
238
  *
231
239
  * @return array
232
240
  * @internal
@@ -236,13 +244,20 @@ function ( jQuery, PluginManager ) {
236
244
  var
237
245
  plugins = jQuery('[data-aloha-plugins]').data('aloha-plugins');
238
246
 
247
+ // load aloha plugins from config
248
+ if ( typeof Aloha.settings.plugins != 'undefined' && typeof Aloha.settings.plugins.load != 'undefined' ) {
249
+ plugins = Aloha.settings.plugins.load;
250
+ if (plugins instanceof Array) {
251
+ return plugins;
252
+ }
253
+ }
254
+
239
255
  // Determine Plugins
240
256
  if ( typeof plugins === 'string' && plugins !== "") {
241
257
  return plugins.replace(/\s+/g, '').split(',');
242
258
  }
243
259
  // Return
244
260
  return [];
245
-
246
261
  },
247
262
 
248
263
  /**
@@ -521,6 +536,7 @@ function ( jQuery, PluginManager ) {
521
536
 
522
537
  /**
523
538
  * Determines the Aloha Url
539
+ * Uses Aloha.settings.baseUrl if set.
524
540
  * @method
525
541
  * @return {String} alohaUrl
526
542
  */
@@ -528,7 +544,11 @@ function ( jQuery, PluginManager ) {
528
544
  // aloha base path is defined by a script tag with 2 data attributes
529
545
  var requireJs = jQuery('[data-aloha-plugins]'),
530
546
  baseUrl = ( requireJs.length ) ? requireJs[0].src.replace( /\/?aloha.js$/ , '' ) : '';
531
-
547
+
548
+ if ( typeof Aloha.settings.baseUrl === "string" ) {
549
+ baseUrl = Aloha.settings.baseUrl;
550
+ }
551
+
532
552
  return baseUrl;
533
553
  },
534
554
 
@@ -557,4 +577,4 @@ function ( jQuery, PluginManager ) {
557
577
  });
558
578
 
559
579
  return Aloha;
560
- });
580
+ });
@@ -1,6 +1,18 @@
1
+ /**
2
+ * ecma5schims.js - Shim for ECMA5 compatibility
3
+ * (http://en.wikipedia.org/wiki/Shim_%28computing%29)
4
+ *
5
+ * A shim library that implements common functions that are missing on some
6
+ * environments in order to complete ECMA5 compatibility across all major
7
+ * browsers.
8
+ *
9
+ * TODO: This code needs to be refactored so as to conform to Aloha coding
10
+ * standards. It is also severly lacking in documentation. Please take
11
+ * note of: https://github.com/alohaeditor/Aloha-Editor/wiki/Commit-Checklist .
12
+ */
1
13
 
2
- define([],
3
- function(){
14
+ define([], function(){
15
+
4
16
 
5
17
  var shims = {
6
18
  // Function bind
@@ -236,12 +248,16 @@ function(){
236
248
  if (node2 != useNode2) useNode2.parentNode.removeChild(useNode2);
237
249
  return result;
238
250
 
239
-
240
251
  //node.ownerDocument gives the document object, which isn't the right info for a disconnect
241
- function getRootParent(node) {
242
- do { var parent = node; }
243
- while (node = node.parentNode);
244
- return parent;
252
+ function getRootParent( node ) {
253
+ var parent = null;
254
+
255
+ if ( node ) {
256
+ do { parent = node; }
257
+ while ( node = node.parentNode );
258
+ }
259
+
260
+ return parent;
245
261
  }
246
262
 
247
263
  //Compare Position - MIT Licensed, John Resig; http://ejohn.org/blog/comparing-document-position/
@@ -52,6 +52,12 @@ define( [
52
52
  Aloha.settings.contentHandler = {};
53
53
  }
54
54
 
55
+ var defaultContentSerializer = function(editableElement){
56
+ return jQuery(editableElement).html();
57
+ };
58
+
59
+ var contentSerializer = defaultContentSerializer;
60
+
55
61
  /**
56
62
  * Editable object
57
63
  * @namespace Aloha
@@ -76,8 +82,9 @@ define( [
76
82
 
77
83
  // delimiters, timer and idle for smartContentChange
78
84
  // smartContentChange triggers -- tab: '\u0009' - space: '\u0020' - enter: 'Enter'
85
+ // backspace: U+0008 - delete: U+007F
79
86
  this.sccDelimiters = [ ':', ';', '.', '!', '?', ',',
80
- unescape( '%u0009' ), unescape( '%u0020' ), 'Enter' ];
87
+ unescape( '%u0009' ), unescape( '%u0020' ), unescape( '%u0008' ), unescape( '%u007F' ), 'Enter' ];
81
88
  this.sccIdle = 5000;
82
89
  this.sccDelay = 500;
83
90
  this.sccTimerIdle = false;
@@ -200,8 +207,13 @@ define( [
200
207
  // if it does not handle the keyStroke it returns true and therefore all other
201
208
  // events (incl. browser's) continue
202
209
  me.obj.keydown( function( event ) {
210
+ var letEventPass = Markup.preProcessKeyStrokes( event );
203
211
  me.keyCode = event.which;
204
- return Markup.preProcessKeyStrokes( event );
212
+ if (!letEventPass) {
213
+ // the event will not proceed to key press, therefore trigger smartContentChange
214
+ me.smartContentChange( event );
215
+ }
216
+ return letEventPass;
205
217
  } );
206
218
 
207
219
  // handle keypress
@@ -688,19 +700,32 @@ define( [
688
700
  this.removePlaceholder( clonedObj );
689
701
  PluginManager.makeClean( clonedObj );
690
702
 
691
- /*
692
- //also deactivated for now. like initEditable. just in case ...
693
- var content = clonedObj.html()
694
- if ( typeof Aloha.settings.contentHandler.getContents === 'undefined' ) {
695
- Aloha.settings.contentHandler.getContents = Aloha.defaults.contentHandler.getContents;
703
+ return asObject ? clonedObj.contents() : contentSerializer(clonedObj[0]);
704
+ },
705
+
706
+ /**
707
+ * Set the contents of this editable as a HTML string
708
+ * @param content as html
709
+ * @param return as object or html string
710
+ * @return contents of the editable
711
+ */
712
+ setContents: function( content, asObject ) {
713
+ var reactivate = null;
714
+
715
+ if ( Aloha.getActiveEditable() === this ) {
716
+ Aloha.deactivateEditable();
717
+ reactivate = this;
718
+ }
719
+
720
+ this.obj.html( content );
721
+
722
+ if ( null !== reactivate ) {
723
+ reactivate.activate();
696
724
  }
697
- content = ContentHandlerManager.handleContent( content, {
698
- contenthandler: Aloha.settings.contentHandler.getContents
699
- } );
700
- clonedObj.html( content );
701
- */
702
725
 
703
- return asObject ? clonedObj.contents() : clonedObj.html();
726
+ this.smartContentChange({type : 'set-contents'});
727
+
728
+ return asObject ? this.obj.contents() : contentSerializer(this.obj[0]);
704
729
  },
705
730
 
706
731
  /**
@@ -849,6 +874,24 @@ define( [
849
874
  this.snapshotContent = this.getContents();
850
875
  return ret;
851
876
  }
852
-
853
877
  } );
878
+
879
+ /**
880
+ * Sets the serializer function to be used for the contents of all editables.
881
+ *
882
+ * The default content serializer will just call the jQuery.html()
883
+ * function on the editable element (which gets the innerHTML property).
884
+ *
885
+ * This method is a static class method and will affect the result
886
+ * of editable.getContents() for all editables that have been or
887
+ * will be constructed.
888
+ *
889
+ * @param serializerFunction
890
+ * A function that accepts a DOM element and returns the serialized
891
+ * XHTML of the element contents (excluding the start and end tag of
892
+ * the passed element).
893
+ */
894
+ Aloha.Editable.setContentSerializer = function( serializerFunction ) {
895
+ contentSerializer = serializerFunction;
896
+ };
854
897
  } );
@@ -6252,6 +6252,7 @@ commands["delete"] = {
6252
6252
 
6253
6253
  // collapse whitespace sequences
6254
6254
  collapseWhitespace(node, range);
6255
+ offset = range.startOffset;
6255
6256
 
6256
6257
  // "If node is a Text node and offset is not zero, call collapse(node,
6257
6258
  // offset) on the Selection. Then delete the contents of the range with
@@ -6845,6 +6846,7 @@ commands.forwarddelete = {
6845
6846
 
6846
6847
  // collapse whitespace in the node, if it is a text node
6847
6848
  collapseWhitespace(node, range);
6849
+ offset = range.startOffset;
6848
6850
 
6849
6851
  // "If node is a Text node and offset is not node's length:"
6850
6852
  if (node.nodeType == $_.Node.TEXT_NODE
@@ -7641,11 +7643,13 @@ commands.insertparagraph = {
7641
7643
  // container name) on the context object."
7642
7644
  var newContainer = document.createElement(newContainerName);
7643
7645
 
7644
- // "Copy all attributes of container to new container."
7645
- for (var i = 0; i < container.attributes.length; i++) {
7646
- if (typeof newContainer.setAttributeNS === 'function') {
7646
+ // "Copy all non empty attributes of the container to new container."
7647
+ for ( var i = 0; i < container.attributes.length; i++ ) {
7648
+ if ( typeof newContainer.setAttributeNS === 'function' ) {
7647
7649
  newContainer.setAttributeNS(container.attributes[i].namespaceURI, container.attributes[i].name, container.attributes[i].value);
7648
- } else {
7650
+ } else if ( container.attributes[i].value.length > 0
7651
+ && container.attributes[i].value != 'null'
7652
+ && container.attributes[i].value > 0) {
7649
7653
  newContainer.setAttribute(container.attributes[i].name, container.attributes[i].value);
7650
7654
  }
7651
7655
  }
@@ -8303,4 +8307,4 @@ return {
8303
8307
  queryCommandSupported: myQueryCommandSupported
8304
8308
  }
8305
8309
  }); // end define
8306
- // vim: foldmarker=@{,@} foldmethod=marker
8310
+ // vim: foldmarker=@{,@} foldmethod=marker
@@ -64,8 +64,7 @@ function(Aloha, jQuery, Ext, Class, console) {
64
64
  getExtComponent: function () {
65
65
  var that = this;
66
66
 
67
- if (typeof this.extPanel === 'undefined') {
68
- // generate the panel here
67
+ if (!this.extPanel) {
69
68
  this.extPanel = new Ext.Panel({
70
69
  'tbar' : [],
71
70
  'title' : this.label,
@@ -73,13 +72,15 @@ function(Aloha, jQuery, Ext, Class, console) {
73
72
  'bodyStyle': 'display:none',
74
73
  'autoScroll': true
75
74
  });
75
+ }
76
76
 
77
- // add the groups
78
- jQuery.each(this.groups, function(index, group) {
79
- // let each group generate its ext component and add them to the panel
77
+ jQuery.each(this.groups, function(index, group) {
78
+ // let each group generate its ext component and add them to
79
+ // the panel once.
80
+ if (!group.extButtonGroup) {
80
81
  that.extPanel.getTopToolbar().add(group.getExtComponent());
81
- });
82
- }
82
+ }
83
+ });
83
84
 
84
85
  return this.extPanel;
85
86
  },
@@ -192,6 +193,7 @@ function(Aloha, jQuery, Ext, Class, console) {
192
193
  'columns' : columnCount,
193
194
  'items': items
194
195
  });
196
+
195
197
  // jQuery.each(this.fields, function(id, field){
196
198
  // that.buttons.push(field);
197
199
  // });
@@ -265,6 +267,73 @@ function(Aloha, jQuery, Ext, Class, console) {
265
267
  }
266
268
  });
267
269
 
270
+ //=========================================================================
271
+ //
272
+ // Floating Menu
273
+ //
274
+ //=========================================================================
275
+
276
+ var lastFloatingMenuPos = {
277
+ top: null,
278
+ left: null
279
+ };
280
+
281
+ /**
282
+ * Handler for window scroll event. Positions the floating menu
283
+ * appropriately.
284
+ *
285
+ * @param {Aloha.FloatingMenu} floatingmenu
286
+ */
287
+ function onWindowScroll( floatingmenu ) {
288
+ if ( !Aloha.activeEditable ) {
289
+ return;
290
+ }
291
+
292
+ var element = floatingmenu.obj;
293
+ var editablePos = Aloha.activeEditable.obj.offset();
294
+ var isTopAligned = floatingmenu.behaviour === 'topalign';
295
+ var isAppended = floatingmenu.behaviour === 'append';
296
+ var isManuallyPinned = floatingmenu.pinned
297
+ && ( parseInt( element.css( 'left' ), 10 )
298
+ != ( editablePos.left
299
+ + floatingmenu.horizontalOffset
300
+ ) );
301
+
302
+ // no calculation when pinned manually or has behaviour 'append'
303
+ if ( isTopAligned && isManuallyPinned || isAppended ) {
304
+ return;
305
+ }
306
+
307
+ var floatingmenuHeight = element.height();
308
+ var scrollTop = jQuery( document ).scrollTop();
309
+
310
+ // This value is what the top position of the floating menu *would* be
311
+ // if we tried to position it above the active editable.
312
+ var floatingmenuTop = editablePos.top - floatingmenuHeight
313
+ + floatingmenu.marginTop
314
+ - floatingmenu.topalignOffset;
315
+
316
+ // The floating menu does not fit in the space between the top of the
317
+ // viewport and the editable, so position it at the top of the viewport
318
+ // and over the editable.
319
+ if ( scrollTop > floatingmenuTop ) {
320
+ editablePos.top = isTopAligned
321
+ ? scrollTop + floatingmenu.marginTop
322
+ : floatingmenu.marginTop;
323
+
324
+ // There is enough space on top of the editable to fit the entire
325
+ // floating menu, so we do so.
326
+ } else if ( scrollTop <= floatingmenuTop ) {
327
+ editablePos.top -= floatingmenuHeight
328
+ + ( isTopAligned
329
+ ? floatingmenu.marginTop +
330
+ floatingmenu.topalignOffset
331
+ : 0 );
332
+ }
333
+
334
+ floatingmenu.floatTo( editablePos );
335
+ }
336
+
268
337
  /**
269
338
  * Aloha's Floating Menu
270
339
  * @namespace Aloha
@@ -344,16 +413,30 @@ function(Aloha, jQuery, Ext, Class, console) {
344
413
  window: jQuery(window),
345
414
 
346
415
  /**
347
- * define floating menu float behaviour. meant to be adjusted via
348
- * GENTICS.Aloha.settings.floatingmenu.behaviour
349
- * set it to 'float' for standard behaviour, or 'topalign' for a fixed fm
416
+ * Aloha.settings.floatingmenu.behaviour
417
+ *
418
+ * Is used to define the floating menu (fm) float behaviour.
419
+ *
420
+ * available:
421
+ * 'float' (default) the fm will float next to the position where the caret is,
422
+ * 'topalign' the fm is fixed above the contentEditable which is active,
423
+ * 'append' the fm is appended to the defined 'element' element position (top/left)
350
424
  */
351
425
  behaviour: 'float',
352
426
 
427
+ /**
428
+ * Aloha.settings.floatingmenu.element
429
+ *
430
+ * Is used to define the element where the floating menu is positioned when
431
+ * Aloha.settings.floatingmenu.behaviour is set to 'append'
432
+ *
433
+ */
434
+ element: 'floatingmenu',
435
+
353
436
  /**
354
437
  * topalign offset to be used for topalign behavior
355
438
  */
356
- topalignOffset: 90,
439
+ topalignOffset: 0,
357
440
 
358
441
  /**
359
442
  * topalign offset to be used for topalign behavior
@@ -364,7 +447,7 @@ function(Aloha, jQuery, Ext, Class, console) {
364
447
  * will only be hounoured when behaviour is set to 'topalign'. Adds a margin,
365
448
  * so the floating menu is not directly attached to the top of the page
366
449
  */
367
- marginTop: 0,
450
+ marginTop: 10,
368
451
 
369
452
  /**
370
453
  * Define whether the floating menu shall be draggable or not via Aloha.settings.floatingmanu.draggable
@@ -372,6 +455,12 @@ function(Aloha, jQuery, Ext, Class, console) {
372
455
  */
373
456
  draggable: true,
374
457
 
458
+ /**
459
+ * Define whether the floating menu shall be pinned or not via Aloha.settings.floatingmanu.pin
460
+ * Default is: false
461
+ */
462
+ pin: false,
463
+
375
464
  /**
376
465
  * A list of all buttons that have been added to the floatingmenu
377
466
  * This needs to be tracked, as adding buttons twice will break the fm
@@ -391,38 +480,58 @@ function(Aloha, jQuery, Ext, Class, console) {
391
480
  init: function() {
392
481
 
393
482
  // check for behaviour setting of the floating menu
394
- if (Aloha.settings.floatingmenu) {
395
-
396
- if (typeof Aloha.settings.floatingmenu.draggable === 'boolean') {
483
+ if ( Aloha.settings.floatingmenu ) {
484
+ if ( typeof Aloha.settings.floatingmenu.draggable ===
485
+ 'boolean' ) {
397
486
  this.draggable = Aloha.settings.floatingmenu.draggable;
398
487
  }
399
- if (typeof Aloha.settings.floatingmenu.behaviour === 'string') {
488
+
489
+ if ( typeof Aloha.settings.floatingmenu.behaviour ===
490
+ 'string' ) {
400
491
  this.behaviour = Aloha.settings.floatingmenu.behaviour;
401
492
  }
402
- if (typeof Aloha.settings.floatingmenu.topalignOffset !== 'undefined') {
403
- this.topalignOffset = Aloha.settings.floatingmenu.topalignOffset;
493
+
494
+ if ( typeof Aloha.settings.floatingmenu.topalignOffset !==
495
+ 'undefined' ) {
496
+ this.topalignOffset = parseInt(
497
+ Aloha.settings.floatingmenu.topalignOffset, 10 );
404
498
  }
405
- if (typeof Aloha.settings.floatingmenu.horizontalOffset !== 'undefined') {
406
- this.horizontalOffset = Aloha.settings.floatingmenu.horizontalOffset;
499
+
500
+ if ( typeof Aloha.settings.floatingmenu.horizontalOffset !==
501
+ 'undefined' ) {
502
+ this.horizontalOffset = parseInt(
503
+ Aloha.settings.floatingmenu.horizontalOffset , 10 );
407
504
  }
408
- if (typeof Aloha.settings.floatingmenu.marginTop === 'number') {
409
- this.marginTop = Aloha.settings.floatingmenu.marginTop;
505
+
506
+ if ( typeof Aloha.settings.floatingmenu.marginTop ===
507
+ 'number' ) {
508
+ this.marginTop = parseInt(
509
+ Aloha.settings.floatingmenu.marginTop , 10 );
410
510
  }
411
- //We just check for undefined
412
- if (typeof Aloha.settings.floatingmenu.width !== 'undefined') {
413
- //Try to pars it
414
- try {
415
- var parsed = parseInt(Aloha.settings.floatingmenu.width);
416
- this.width = Aloha.settings.floatingmenu.width;
417
- } catch(e) {
418
- //do nothing.
419
- }
511
+
512
+ if ( typeof Aloha.settings.floatingmenu.element ===
513
+ 'string' ) {
514
+ this.element = Aloha.settings.floatingmenu.element;
515
+ }
516
+ if ( typeof Aloha.settings.floatingmenu.pin ===
517
+ 'boolean' ) {
518
+ this.pin = Aloha.settings.floatingmenu.pin;
519
+ }
520
+
521
+
522
+ if ( typeof Aloha.settings.floatingmenu.width !==
523
+ 'undefined' ) {
524
+ this.width = parseInt( Aloha.settings.floatingmenu.width,
525
+ 10 );
420
526
  }
421
527
  }
422
528
 
423
529
  jQuery.storage = new jQuery.store();
530
+
424
531
  this.currentScope = 'Aloha.global';
532
+
425
533
  var that = this;
534
+
426
535
  this.window.unload(function () {
427
536
  // store fm position if the panel is pinned to be able to restore it next time
428
537
  if (that.pinned) {
@@ -462,7 +571,7 @@ function(Aloha, jQuery, Ext, Class, console) {
462
571
  });
463
572
 
464
573
  if (typeof Aloha.settings.toolbar === 'object') {
465
- this.fromConfig = true;
574
+ this.fromConfig = true;
466
575
  }
467
576
  },
468
577
 
@@ -580,6 +689,10 @@ function(Aloha, jQuery, Ext, Class, console) {
580
689
  that.left = this.x;
581
690
  that.top = top;
582
691
 
692
+ // store the last floating menu position when the floating menu was dragged around
693
+ lastFloatingMenuPos.left = that.left;
694
+ lastFloatingMenuPos.top = that.top;
695
+
583
696
  this.panel.setPosition(this.x, top);
584
697
  that.refreshShadow();
585
698
  this.panel.shadow.show();
@@ -630,8 +743,10 @@ function(Aloha, jQuery, Ext, Class, console) {
630
743
  });
631
744
 
632
745
  // adapt the shadow
633
- that.extTabPanel.shadow.show();
634
- that.refreshShadow();
746
+ if (that.extTabPanel.isVisible()) {
747
+ that.extTabPanel.shadow.show();
748
+ that.refreshShadow();
749
+ }
635
750
  }
636
751
  }
637
752
  },
@@ -640,6 +755,7 @@ function(Aloha, jQuery, Ext, Class, console) {
640
755
 
641
756
 
642
757
  }
758
+
643
759
  // add the tabs
644
760
  jQuery.each(this.tabs, function(index, tab) {
645
761
  // let each tab generate its ext component and add them to the panel
@@ -651,8 +767,10 @@ function(Aloha, jQuery, Ext, Class, console) {
651
767
  });
652
768
 
653
769
  // add the dropshadow
654
- this.extTabPanel.shadow = jQuery('<div id="aloha-floatingmenu-shadow" class="aloha-shadow">&#160;</div>');
655
- jQuery('body').append(this.extTabPanel.shadow);
770
+ if (!this.extTabPanel.shadow) {
771
+ this.extTabPanel.shadow = jQuery('<div id="aloha-floatingmenu-shadow" class="aloha-shadow">&#160;</div>').hide();
772
+ jQuery('body').append(this.extTabPanel.shadow);
773
+ }
656
774
 
657
775
  // add an empty pin tab item, store reference
658
776
  pinTab = this.extTabPanel.add({
@@ -686,7 +804,7 @@ function(Aloha, jQuery, Ext, Class, console) {
686
804
  this.obj = jQuery(this.extTabPanel.getEl().dom);
687
805
 
688
806
  if (jQuery.storage.get('Aloha.FloatingMenu.pinned') == 'true') {
689
- this.togglePin();
807
+ //this.togglePin();
690
808
 
691
809
  this.top = parseInt(jQuery.storage.get('Aloha.FloatingMenu.top'),10);
692
810
  this.left = parseInt(jQuery.storage.get('Aloha.FloatingMenu.left'),10);
@@ -715,13 +833,26 @@ function(Aloha, jQuery, Ext, Class, console) {
715
833
  this.obj.mousedown(function (e) {
716
834
  e.originalEvent.stopSelectionUpdate = true;
717
835
  Aloha.eventHandled = true;
718
- // e.stopSelectionUpdate = true;
836
+ //e.stopSelectionUpdate = true;
719
837
  });
838
+
720
839
  this.obj.mouseup(function (e) {
721
840
  e.originalEvent.stopSelectionUpdate = true;
722
841
  Aloha.eventHandled = false;
723
842
  });
724
843
 
844
+ jQuery( window ).scroll(function() {
845
+ onWindowScroll( that );
846
+ });
847
+
848
+ // don't display the drag handle bar / pin when floating menu is not draggable
849
+ if ( !that.draggable ) {
850
+ jQuery('.aloha-floatingmenu').hover( function() {
851
+ jQuery(this).css({background: 'none'});
852
+ jQuery('.aloha-floatingmenu-pin').hide();
853
+ });
854
+ }
855
+
725
856
  // adjust float behaviour
726
857
  if (this.behaviour === 'float') {
727
858
  // listen to selectionChanged event
@@ -733,56 +864,85 @@ function(Aloha, jQuery, Ext, Class, console) {
733
864
  }
734
865
  }
735
866
  });
736
- } else if (this.behaviour === 'topalign') {
867
+ } else if (this.behaviour === 'append' ) {
868
+ var p = jQuery( "#" + that.element );
869
+ var position = p.offset();
870
+
871
+ if ( !position ) {
872
+ Aloha.Log.warn(that, 'Invalid element HTML ID for floating menu: ' + that.element);
873
+ return false;
874
+ }
875
+
876
+ // set the position so that it does not float on the first editable activation
877
+ this.floatTo( position );
878
+
879
+ if ( this.pin ) {
880
+ this.togglePin( true );
881
+ }
882
+
883
+ Aloha.bind( 'aloha-editable-activated', function( event, data ) {
884
+ if ( that.pinned ) {
885
+ return;
886
+ }
887
+ that.floatTo( position );
888
+ });
889
+
890
+ } else if ( this.behaviour === 'topalign' ) {
737
891
  // topalign will retain the user's pinned status
738
892
  // TODO maybe the pin should be hidden in that case?
739
- this.togglePin(false);
740
-
741
- // float the fm to each editable that is activated
742
- Aloha.bind('aloha-editable-activated', function(event, data) {
743
- var p = data.editable.obj.offset();
744
- p.top -= that.topalignOffset;
745
- p.left += that.horizontalOffset;
746
- if (p.top < jQuery(document).scrollTop()) {
747
- // scrollpos is below top of editable
748
- that.obj.css('top', jQuery(document).scrollTop() + that.marginTop);
749
- that.obj.css('left', p.left);
750
- that.togglePin(true);
751
- } else {
752
- // scroll pos is above top of editable
753
- that.floatTo(p);
754
- }
755
- });
893
+ this.togglePin( false );
756
894
 
757
- // fm scroll behaviour
758
- jQuery(window).scroll(function () {
759
- if (!Aloha.activeEditable) {
760
- return;
761
- }
762
- var pos = Aloha.activeEditable.obj.offset(),
763
- fmHeight = that.obj.height(),
764
- scrollTop = jQuery(document).scrollTop();
765
-
766
- if (scrollTop > (pos.top - fmHeight - 6 - that.marginTop)) {
767
- // scroll pos is lower than top of editable
768
- that.togglePin(true);
769
- that.obj.css('top', that.marginTop);
770
- } else if (scrollTop <= (pos.top - fmHeight - 6 - that.marginTop)) {
771
- // scroll pos is above top of editable
772
- if (that.behaviour === 'topalign') {
773
- pos.top = Aloha.activeEditable.obj.offset().top - that.topalignOffset;
774
- pos.left = Aloha.activeEditable.obj.offset().left + that.horizontalOffset;
895
+ // Float the menu to the editable that is activated.
896
+ Aloha.bind( 'aloha-editable-activated', function( event, data ) {
897
+ if ( that.pinned ) {
898
+ return;
899
+ }
900
+
901
+ // FIXME: that.obj.height() does not return the correct
902
+ // height of the editable. We need to fix this, and
903
+ // not hard-code the height as we currently do.
904
+ var editable = data.editable.obj;
905
+ var floatingmenuHeight = 90;
906
+ var editablePos = editable.offset();
907
+ var isFloatingmenuAboveViewport = ( (
908
+ editablePos.top - floatingmenuHeight )
909
+ < jQuery( document ).scrollTop() );
910
+
911
+ if ( isFloatingmenuAboveViewport ) {
912
+ // Since we don't have space to place the floatingmenu
913
+ // above the editable, we want to place it over the
914
+ // editable instead. But if the editable is shorter
915
+ // than the floatingmenu, it would be completely
916
+ // covered by it, and so, in such cases, we position
917
+ // the editable at the bottom of the short editable.
918
+ editablePos.top = ( editable.height()
919
+ < floatingmenuHeight )
920
+ ? editablePos.top + editable.height()
921
+ : jQuery( document ).scrollTop();
922
+
923
+ editablePos.top += that.marginTop;
775
924
  } else {
776
- pos.top -= fmHeight + 6;
925
+ editablePos.top -= floatingmenuHeight
926
+ + that.topalignOffset;
777
927
  }
778
- that.togglePin(false);
779
- that.floatTo(pos);
780
- } else if (scrollTop > pos.top + Aloha.activeEditable.obj.height() - fmHeight) {
781
- // scroll pos is below editable
782
- that.togglePin(false);
783
- }
784
- });
785
- }
928
+
929
+ editablePos.left += that.horizontalOffset;
930
+
931
+ var HORIZONTAL_PADDING = 10;
932
+ // Calculate by how much the floating menu is pocking
933
+ // outside the width of the viewport. A positive number
934
+ // means that it is outside the viewport, negative means
935
+ // it is within the viewport.
936
+ var overhang = ( ( editablePos.left + that.width
937
+ + HORIZONTAL_PADDING ) - jQuery(window).width() );
938
+
939
+ if ( overhang > 0 ) {
940
+ editablePos.left -= overhang;
941
+ }
942
+
943
+ that.floatTo( editablePos );
944
+ });
945
+ }
786
946
  },
787
947
 
788
948
  /**
@@ -961,6 +1121,11 @@ function(Aloha, jQuery, Ext, Class, console) {
961
1121
  Aloha.Log.debug(this, 'doLayout called for FloatingMenu, scope is ' + this.currentScope);
962
1122
  }
963
1123
 
1124
+ // if there's no floatingmenu don't do anything
1125
+ if ( typeof this.extTabPanel === 'undefined' ) {
1126
+ return false;
1127
+ }
1128
+
964
1129
  var that = this,
965
1130
  firstVisibleTab = false,
966
1131
  activeExtTab = this.extTabPanel.getActiveTab(),
@@ -1186,7 +1351,10 @@ function(Aloha, jQuery, Ext, Class, console) {
1186
1351
 
1187
1352
  // if the floating menu would be placed higher than the top of the screen...
1188
1353
  if ( top < scrollTop) {
1189
- top += 50 + GENTICS.Utils.Position.ScrollCorrection.top;
1354
+ top += 80 + GENTICS.Utils.Position.ScrollCorrection.top;
1355
+ // 80px if editable element is eg h1; 50px was fine for p;
1356
+ // todo: maybe just use GENTICS.Utils.Position.ScrollCorrection.top with a better value?
1357
+ // check where this is also used ...
1190
1358
  }
1191
1359
 
1192
1360
  // if the floating menu would float off the bottom of the screen
@@ -1220,24 +1388,47 @@ function(Aloha, jQuery, Ext, Class, console) {
1220
1388
  return;
1221
1389
  }
1222
1390
 
1223
- var that = this,
1224
- fmpos = this.obj.offset();
1391
+ var floatingmenu = this,
1392
+ fmpos = this.obj.offset(),
1393
+ lastLeft,
1394
+ lastTop;
1395
+
1396
+ if ( lastFloatingMenuPos.left === null ) {
1397
+ lastLeft = fmpos.left;
1398
+ lastTop = fmpos.top;
1399
+ } else {
1400
+ lastLeft = lastFloatingMenuPos.left;
1401
+ lastTop = lastFloatingMenuPos.top;
1402
+ }
1225
1403
 
1226
- // move to the new position
1227
- if (fmpos.left != position.left || fmpos.top != position.top) {
1228
- this.obj.animate({
1229
- top: position.top,
1404
+ // Place the floatingmenu to the last place the user had seen it,
1405
+ // then animate it into its new position.
1406
+ if ( lastLeft != position.left || lastTop != position.top ) {
1407
+ this.obj.offset({
1408
+ left: lastLeft,
1409
+ top: lastTop
1410
+ });
1411
+
1412
+ this.obj.animate( {
1413
+ top: position.top,
1230
1414
  left: position.left
1231
1415
  }, {
1232
1416
  queue : false,
1233
- step : function (step, props) {
1417
+ step : function( step, props ) {
1234
1418
  // update position reference
1235
- if (props.prop == 'top') {
1236
- that.top = props.now;
1237
- } else if (props.prop == 'left') {
1238
- that.left = props.now;
1419
+ if ( props.prop === 'top' ) {
1420
+ floatingmenu.top = props.now;
1421
+ } else if ( props.prop === 'left' ) {
1422
+ floatingmenu.left = props.now;
1239
1423
  }
1240
- that.refreshShadow(false);
1424
+
1425
+ floatingmenu.refreshShadow( false );
1426
+ },
1427
+ complete: function() {
1428
+ // When the animation is over, remember the floatingmenu's
1429
+ // final resting position.
1430
+ lastFloatingMenuPos.left = floatingmenu.left;
1431
+ lastFloatingMenuPos.top = floatingmenu.top;
1241
1432
  }
1242
1433
  });
1243
1434
  }
@@ -1302,3 +1493,4 @@ function(Aloha, jQuery, Ext, Class, console) {
1302
1493
 
1303
1494
  return menu;
1304
1495
  });
1496
+