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
@@ -9,6 +9,26 @@
9
9
  * www.jstree.com/documentation/core
10
10
  * www.trirand.com/blog (jqGrid)
11
11
  * layout.jquery-dev.net
12
+ *
13
+ * NOTE: regarding 'jquery-plugin' RequireJS loader:
14
+ * due to Cross-Origin Resource Sharing (CORS) / Access-Control-Allow-Origin
15
+ * problems with the CDN the jQuery plugins got a litte rewrite.
16
+ *
17
+ * ATTENTION: when updating the plugins you need to insert at the top of the file:
18
+ *
19
+ * define(['aloha/jquery'], function(jQuery) {
20
+ * var $ = jQuery;
21
+ *
22
+ * and at the end of the file:
23
+ *
24
+ * });
25
+ *
26
+ * see: README https://github.com/jrburke/require-jquery/ or
27
+ * http://requirejs.org/docs/jquery.html
28
+ *
29
+ * others: depend.js from https://github.com/millermedeiros/requirejs-plugins
30
+ *
31
+ * todo: think about if using order plugin or priority config can help us here
12
32
  */
13
33
  define( [
14
34
 
@@ -19,11 +39,10 @@ define( [
19
39
  // this will load the correct language pack needed for the browser
20
40
  'browser/locale',
21
41
  'css!browser/css/browsercombined.css',
22
- // 'jquery-plugin!browser/vendor/grid.locale.en.js', // we use 'browser/locale' instead
23
- 'jquery-plugin!browser/vendor/jquery.ui',
24
- 'jquery-plugin!browser/vendor/ui-layout',
25
- 'jquery-plugin!browser/vendor/jquery.jqGrid',
26
- 'jquery-plugin!browser/vendor/jquery.jstree'
42
+ 'browser/vendor/jquery.ui',
43
+ 'browser/vendor/ui-layout',
44
+ 'browser/vendor/jquery.jqGrid',
45
+ 'browser/vendor/jquery.jstree'
27
46
 
28
47
  ], function ( jQuery, Class, i18n, Console ) {
29
48
 
@@ -580,6 +599,10 @@ var Browser = Class.extend({
580
599
  },
581
600
  json_data: {
582
601
  data: function (node, callback) {
602
+ if (window.GCN && !window.GCN.sid) {
603
+ // return early if used in GCN context but no session id is set
604
+ return;
605
+ }
583
606
  if (that.repositoryManager) {
584
607
  that.jstree_callback = callback;
585
608
  that.fetchSubnodes.call(that, node, callback);
@@ -14,8 +14,8 @@
14
14
  define( [
15
15
  'aloha/jquery',
16
16
  'i18n!browser/nls/i18n',
17
- 'jquery-plugin!browser/../vendor/grid.locale.en',
18
- 'jquery-plugin!browser/../vendor/grid.locale.de'
17
+ 'browser/../vendor/grid.locale.en',
18
+ 'browser/../vendor/grid.locale.de'
19
19
  ], function ( jQuery, i18n ) {
20
20
  var locale = i18n[ 'jgrid.locale' ] || 'en';
21
21
  if ( typeof jQuery.jgrid == 'undefined' ) {
@@ -1,3 +1,6 @@
1
+ define(['aloha/jquery'], function(jQuery) {
2
+ var $ = jQuery;
3
+
1
4
  ;(function($){
2
5
  /**
3
6
  * jqGrid German Translation
@@ -131,4 +134,6 @@ $.jgrid_de = {
131
134
  idName: 'id'
132
135
  }
133
136
  };
134
- })(jQuery);
137
+ })(jQuery);
138
+
139
+ });
@@ -1,3 +1,6 @@
1
+ define(['aloha/jquery'], function(jQuery) {
2
+ var $ = jQuery;
3
+
1
4
  ;(function($){
2
5
  /**
3
6
  * jqGrid English Translation
@@ -127,3 +130,5 @@ $.jgrid_en = {
127
130
  }
128
131
  };
129
132
  })(jQuery);
133
+
134
+ });
@@ -1,3 +1,6 @@
1
+ define(['aloha/jquery'], function(jQuery) {
2
+ var $ = jQuery;
3
+
1
4
  /*
2
5
  * jqGrid 4.0.0 - jQuery Grid
3
6
  * Copyright (c) 2008, Tony Tomov, tony@trirand.com
@@ -465,3 +468,5 @@ true;if(e.beforedrop&&a.isFunction(e.beforedrop)){d=e.beforedrop.call(this,h,j,i
465
468
  hoverClass:"ui-state-hover"},drag_opts:{revert:"invalid",helper:"clone",cursor:"move",appendTo:"#jqgrid_dnd",zIndex:5E3},dropbyname:false,droppos:"first",autoid:true,autoidprefix:"dnd_"},b||{});if(b.connectWith){b.connectWith=b.connectWith.split(",");b.connectWith=a.map(b.connectWith,function(e){return a.trim(e)});a.data(c,"dnd",b);c.p.reccount!="0"&&!c.p.jqgdnd&&g();c.p.jqgdnd=true;for(var f=0;f<b.connectWith.length;f++)a(b.connectWith[f]).droppable(a.isFunction(b.drop)?b.drop.call(a(c),b):b.drop)}}}})},
466
469
  gridResize:function(b){return this.each(function(){var g=this;if(g.grid&&a.fn.resizable){b=a.extend({},b||{});if(b.alsoResize){b._alsoResize_=b.alsoResize;delete b.alsoResize}else b._alsoResize_=false;if(b.stop&&a.isFunction(b.stop)){b._stop_=b.stop;delete b.stop}else b._stop_=false;b.stop=function(c,f){a(g).jqGrid("setGridParam",{height:a("#gview_"+g.p.id+" .ui-jqgrid-bdiv").height()});a(g).jqGrid("setGridWidth",f.size.width,b.shrinkToFit);b._stop_&&b._stop_.call(g,c,f)};b.alsoResize=b._alsoResize_?
467
470
  eval("("+("{'#gview_"+g.p.id+" .ui-jqgrid-bdiv':true,'"+b._alsoResize_+"':true}")+")"):a(".ui-jqgrid-bdiv","#gview_"+g.p.id);delete b._alsoResize_;a("#gbox_"+g.p.id).resizable(b)}})}})})(jQuery);
471
+
472
+ });
@@ -1,3 +1,6 @@
1
+ define(['aloha/jquery'], function(jQuery) {
2
+ var $ = jQuery;
3
+
1
4
  /*
2
5
  * jsTree 1.0-rc3
3
6
  * http://jstree.com/
@@ -4541,4 +4544,6 @@
4541
4544
  })(jQuery);
4542
4545
  //*/
4543
4546
 
4544
- })();
4547
+ })();
4548
+
4549
+ });
@@ -1,3 +1,6 @@
1
+ define(['aloha/jquery'], function(jQuery) {
2
+ var $ = jQuery;
3
+
1
4
  /*!
2
5
  * jQuery UI 1.8.1
3
6
  *
@@ -753,4 +756,6 @@ e*2;b.animate(c,f,a.options.easing);for(e=1;e<l;e++)b.animate(i,f,a.options.easi
753
756
  */
754
757
  (function(e){e.effects.transfer=function(a){return this.queue(function(){var b=e(this),c=e(a.options.to),d=c.offset();c={top:d.top,left:d.left,height:c.innerHeight(),width:c.innerWidth()};d=b.offset();var f=e('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments);
755
758
  b.dequeue()})})}})(jQuery);
756
- ;
759
+ ;
760
+
761
+ });
@@ -1,3 +1,6 @@
1
+ define(['aloha/jquery'], function(jQuery) {
2
+ var $ = jQuery;
3
+
1
4
  /*
2
5
  jquery.layout 1.3.0 - Release Candidate 29.14
3
6
  $Date: 2011-02-13 08:00:00 (Sun, 13 Feb 2011) $
@@ -105,4 +108,6 @@ c=m[a];if(b&&b.data("draggable"))c.resizable=!0,b.draggable("enable").bind("mous
105
108
  a.useStateCookie&&a.cookie.autoLoad&&Ea();l.browser={mozilla:f.browser.mozilla,webkit:f.browser.webkit||f.browser.safari,msie:f.browser.msie,isIE6:f.browser.msie&&f.browser.version==6,boxModel:f.support.boxModel};var b=G,c=u.tagName=b.attr("tagName"),d=c=="BODY",e={};u.selector=b.selector.split(".slice")[0];u.ref=c+"/"+u.selector;b.data("layout",da).data("layoutContainer",v).addClass(m.containerClass);b.data("layoutCSS")||(d?(e=f.extend(na(b,"position,margin,padding,border"),{height:b.css("height"),
106
109
  overflow:b.css("overflow"),overflowX:b.css("overflowX"),overflowY:b.css("overflowY")}),c=f("html"),c.data("layoutCSS",{height:"auto",overflow:c.css("overflow"),overflowX:c.css("overflowX"),overflowY:c.css("overflowY")})):e=na(b,"position,margin,padding,border,top,bottom,left,right,width,height,overflow,overflowX,overflowY"),b.data("layoutCSS",e));try{if(d)f("html").css({height:"100%",overflow:"hidden",overflowX:"hidden",overflowY:"hidden"}),f("body").css({position:"relative",height:"100%",overflow:"hidden",
107
110
  overflowX:"hidden",overflowY:"hidden",margin:0,padding:0,border:"none"});else{var e={overflow:"hidden"},h=b.css("position");b.css("height");if(!b.data("layoutRole")&&(!h||!h.match(/fixed|absolute|relative/)))e.position="relative";b.css(e);b.is(":visible")&&b.innerHeight()<2&&alert(D.errContainerHeight.replace(/CONTAINER/,u.ref))}}catch(g){}f.extend(l.container,$(b));Xa();fa();if(a.scrollToBookmarkOnLoad)b=self.location,b.hash&&b.replace(b.hash);Na();a.autoBindCustomButtons&&Za();a.resizeWithWindow&&
108
- !G.data("layoutRole")&&f(window).bind("resize."+v,Va);f(window).bind("unload."+v,Ma);l.initialized=!0;t(null,a.onload_end||a.onload)})();return da}})(jQuery);
111
+ !G.data("layoutRole")&&f(window).bind("resize."+v,Va);f(window).bind("unload."+v,Ma);l.initialized=!0;t(null,a.onload_end||a.onload)})();return da}})(jQuery);
112
+
113
+ });
@@ -136,6 +136,7 @@ define([
136
136
 
137
137
  citations: [],
138
138
  referenceContainer: null,
139
+ settings: null,
139
140
 
140
141
  init: function () {
141
142
  var that = this;
@@ -144,13 +145,24 @@ define([
144
145
  // the plugin
145
146
  if (Aloha.settings &&
146
147
  Aloha.settings.plugins &&
147
- Aloha.settings.plugins.cite &&
148
148
  Aloha.settings.plugins.cite) {
149
149
  var referenceContainer = $(Aloha.settings.plugins.cite.referenceContainer);
150
150
 
151
151
  if (referenceContainer.length > 0) {
152
152
  this.referenceContainer = referenceContainer;
153
153
  }
154
+
155
+ if ( typeof Aloha.settings.plugins.cite != 'undefinded' ) {
156
+ that.settings = Aloha.settings.plugins.cite;
157
+ }
158
+
159
+ if ( typeof that.settings.sidebar === 'undefinded' ) {
160
+ that.settings.sidebar = {};
161
+ }
162
+
163
+ if ( typeof that.settings.sidebar.open === 'undefinded' ) {
164
+ that.settings.sidebar.open = true;
165
+ }
154
166
  }
155
167
 
156
168
  // Add the inline quote button in the floating menu, in the
@@ -332,6 +344,7 @@ define([
332
344
  },
333
345
 
334
346
  addBlockQuote: function () {
347
+ var that = this;
335
348
  var classes = [nsClass('wrapper'), nsClass(++uid)].join(' ');
336
349
  var markup = $(supplant(
337
350
  '<blockquote class="{classes}" data-cite-id="{uid}"></blockquote>',
@@ -347,7 +360,7 @@ define([
347
360
 
348
361
  this.referenceContainer && this.addCiteToReferences(uid);
349
362
 
350
- if (this.sidebar) {
363
+ if (this.sidebar && that.settings.sidebar.open === true) {
351
364
  this.sidebar.open();
352
365
  }
353
366
  // .activatePanel(nsClass('sidebar-panel'), markup);
@@ -361,6 +374,7 @@ define([
361
374
  ));
362
375
  var rangeObject = Aloha.Selection.rangeObject;
363
376
  var foundMarkup;
377
+ var that = this;
364
378
 
365
379
  // now re enable the editable
366
380
  if (Aloha.activeEditable) {
@@ -401,8 +415,8 @@ define([
401
415
  rangeObject.select();
402
416
 
403
417
  this.referenceContainer && this.addCiteToReferences(uid);
404
-
405
- if (this.sidebar) {
418
+
419
+ if (this.sidebar && that.settings.sidebar.open === true) {
406
420
  this.sidebar.open();
407
421
  }
408
422
  // .activatePanel(nsClass('sidebar-panel'), markup);
@@ -98,6 +98,6 @@ function(Aloha, Plugin, jQuery, FloatingMenu, FormatlessPasteHandler, ContentHan
98
98
  i18nCore.t( 'floatingmenu.tab.format' ),
99
99
  1
100
100
  );
101
- },
101
+ }
102
102
  });
103
103
  });
@@ -39,13 +39,23 @@ define( [
39
39
  } );
40
40
 
41
41
  FloatingMenu.addButton(
42
- Links.name,
42
+ 'Aloha.continuoustext',
43
43
  repositoryButton,
44
44
  i18n.t( 'floatingmenu.tab.link' ),
45
45
  1
46
46
  );
47
+ repositoryButton.hide();
47
48
 
48
49
  this.url = Aloha.getAlohaUrl() + '/../plugins/extra/linkbrowser/';
50
+
51
+ Aloha.bind( 'aloha-link-selected', function ( event, rangeObject ) {
52
+ repositoryButton.show();
53
+ FloatingMenu.doLayout();
54
+ });
55
+ Aloha.bind( 'aloha-link-unselected', function ( event, rangeObject ) {
56
+ repositoryButton.hide();
57
+ FloatingMenu.doLayout();
58
+ });
49
59
  },
50
60
 
51
61
  onSelect: function ( item ) {
@@ -66,7 +76,9 @@ define( [
66
76
  range.startOffset = range.endOffset = currentStartOffset;
67
77
  // 4. Invoke the final selection
68
78
  range.select();
69
-
79
+
80
+ Aloha.trigger( 'aloha-link-selected-in-linkbrowser' , item );
81
+
70
82
  // Close the browser lightbox
71
83
  this.close();
72
84
  },
@@ -19,8 +19,8 @@
19
19
  // or set current on server side to be in sync with your backend system
20
20
  "current": "en"
21
21
  },
22
- "repositories": {
23
- "com.gentics.aloha.repositories.LinkList": {
22
+ repositories: {
23
+ linklist: {
24
24
  data: [
25
25
  { name: 'Aloha Developers Wiki', url:'http://www.aloha-editor.com/wiki', type:'website', weight: 0.50 },
26
26
  { name: 'Aloha Editor - The HTML5 Editor', url:'http://aloha-editor.com', type:'website', weight: 0.90 },
@@ -0,0 +1,382 @@
1
+ /*!
2
+ * Aloha Editor
3
+ * Author & Copyright (c) 2010 Gentics Software GmbH
4
+ * aloha-sales@gentics.com
5
+ * Licensed unter the terms of http://www.aloha-editor.com/license.html
6
+ */
7
+
8
+ define(
9
+ ['aloha',
10
+ 'aloha/plugin',
11
+ 'aloha/jquery',
12
+ 'aloha/floatingmenu',
13
+ 'i18n!toc/nls/i18n',
14
+ 'i18n!aloha/nls/i18n',
15
+ 'aloha/console'],
16
+
17
+ function( Aloha, Plugin, jQuery, FloatingMenu, i18n, i18nCore, console ) {
18
+
19
+
20
+ var
21
+ GENTICS = window.GENTICS,
22
+ namespace = 'toc',
23
+ $containers = null,
24
+ allTocs = [];
25
+
26
+ /* helper functions */
27
+ function last(a) { return a[a.length - 1]; }
28
+ function head(a) { return a[0]; }
29
+ function tail(a) { return a.slice(1); }
30
+ function indexOf(a, item) {
31
+ return detect(a, function(cmp){
32
+ return cmp === item;
33
+ });
34
+ }
35
+ function detect(a, f) {
36
+ for (var i = 0; i < a.length; i++) {
37
+ if (f(a[i])) {
38
+ return a[i];
39
+ }
40
+ }
41
+ return null;
42
+ }
43
+ function map(a, f) {
44
+ var result = [];
45
+ for (var i = 0; i < a.length; i++) {
46
+ result.push(f(a[i]));
47
+ }
48
+ return result;
49
+ }
50
+ function each(a, f) {
51
+ map(a, f);
52
+ }
53
+
54
+ /**
55
+ * register the plugin with unique name
56
+ */
57
+ return Plugin.create(namespace, {
58
+
59
+ languages: ['en', 'de'],
60
+ minEntries: 0,
61
+ updateInterval: 5000,
62
+ config: ['toc'],
63
+
64
+ init: function () {
65
+ var that = this;
66
+
67
+ if ( typeof this.settings.minEntries === 'undefined' ) {
68
+ this.settings.minEntries = this.minEntries;
69
+ }
70
+ if ( typeof this.settings.updateInterval === 'undefined' ) {
71
+ this.settings.updateInterval = this.updateInterval;
72
+ }
73
+
74
+ Aloha.bind( 'aloha-editable-activated', function ( event, rangeObject ) {
75
+ if (Aloha.activeEditable) {
76
+ that.cfg = that.getEditableConfig( Aloha.activeEditable.obj );
77
+
78
+ if ( jQuery.inArray( 'toc', that.cfg ) != -1 ) {
79
+ that.insertTocButton.show();
80
+ } else {
81
+ that.insertTocButton.hide();
82
+ return;
83
+ }
84
+ }
85
+ });
86
+
87
+ this.initButtons();
88
+ jQuery(document).ready(function(){
89
+ that.spawn();
90
+ });
91
+
92
+
93
+ },
94
+
95
+ initButtons: function () {
96
+ var scope = 'Aloha.continuoustext',
97
+ that = this;
98
+
99
+ this.insertTocButton = new Aloha.ui.Button({
100
+ 'iconClass' : 'aloha-button aloha-button-ol',
101
+ 'size' : 'small',
102
+ 'onclick' : function () { that.insertAtSelection($containers); },
103
+ 'tooltip' : i18n.t('button.addtoc.tooltip'),
104
+ 'toggle' : false
105
+ });
106
+ FloatingMenu.addButton(
107
+ scope,
108
+ this.insertTocButton,
109
+ i18nCore.t('floatingmenu.tab.insert'),
110
+ 1
111
+ );
112
+ },
113
+
114
+ register: function ($c) {
115
+ $containers = $c;
116
+ },
117
+
118
+ /**
119
+ * inserts a new TOC at the current selection
120
+ */
121
+ insertAtSelection: function($containers){
122
+ $containers = $containers || editableContainers();
123
+ var id = generateId('toc');
124
+
125
+ // we start out with an empty ordered list
126
+ var $tocElement = jQuery("<ol class='toc_root'></ol>").
127
+ attr('id', id).attr('contentEditable', 'false');
128
+ var range = Aloha.Selection.getRangeObject();
129
+ var tocEditable = Aloha.activeEditable;
130
+ var $tocContainer = jQuery(document.getElementById(tocEditable.getId()));
131
+ GENTICS.Utils.Dom.insertIntoDOM($tocElement, range, $tocContainer);
132
+
133
+ this.create(id).register($containers).update().tickTock();
134
+ },
135
+
136
+ /**
137
+ * Spawn containers for all ols with the toc_root class.
138
+ */
139
+ spawn: function ($ctx, $containers) {
140
+
141
+ $ctx = $ctx || jQuery('body');
142
+ $containers = $containers || editableContainers();
143
+ $ctx.find('ol.toc_root').each(function(){
144
+ var id = jQuery(this).attr('id');
145
+ if (!id) {
146
+ id = generateId('toc');
147
+ jQuery(this).attr('id', id);
148
+ }
149
+ that.create(id).register($containers).tickTock();
150
+ });
151
+ },
152
+
153
+ create: function (id) {
154
+ allTocs.push(this);
155
+
156
+ return {
157
+ 'id': id,
158
+ '$containers': jQuery(),
159
+ 'settings': this.settings,
160
+ /**
161
+ * find the TOC root element for this instance
162
+ */
163
+ root: function(){
164
+ return jQuery(document.getElementById(this.id));
165
+ },
166
+ /**
167
+ * registers the given containers with the TOC. a
168
+ * container is an element that may begin or contain
169
+ * sections. Note: use .live on all [contenteditable=true]
170
+ * to catch dynamically added editables.
171
+ * the same containers can be passed in multiple times. they will
172
+ * be registered only once.
173
+ */
174
+ register: function ($containers){
175
+ var self = this;
176
+ // the .add() method ensures that the $containers will be in
177
+ // document order (required for correct TOC order)
178
+
179
+ self.$containers = self.$containers.add($containers);
180
+ self.$containers.filter(function(){
181
+ return !jQuery(this).data(namespace + '.' + self.id + '.listening');
182
+ }).each(function(){
183
+ var $container = jQuery(this);
184
+ $container.data(namespace + '.' + self.id + '.listening', true);
185
+ $container.bind('blur', function(){
186
+ self.cleanupIds($container.get(0));
187
+ self.update($container);
188
+ });
189
+ });
190
+ return self;
191
+ },
192
+ tickTock: function (interval) {
193
+ var self = this;
194
+ interval = interval || this.settings.updateInterval;
195
+ if (!interval) {
196
+ return;
197
+ }
198
+ window.setInterval(function(){
199
+ self.register(editableContainers());
200
+ // TODO: use the active editable instead of rebuilding
201
+ // the entire TOC
202
+ self.update();
203
+ }, interval);
204
+ return self;
205
+ },
206
+ /**
207
+ * there are various ways which can cause duplicate ids on targets
208
+ * (e.g. pressing enter in a heading and writing in a new line, or
209
+ * copy&pasting). Passing a ctx updates only those elements
210
+ * either inside or equal to it.
211
+ * TODO: to be correct this should do
212
+ * a $.contains(documentElement...
213
+ */
214
+ cleanupIds: function (ctx) {
215
+ var ids = [],
216
+ that = this;
217
+ this.headings(this.$containers).each(function(){
218
+ var id = jQuery(this).attr('id');
219
+ if ( (id && -1 != jQuery.inArray(id, ids))
220
+ || ( ctx
221
+ && (jQuery.contains(ctx, this) || ctx === this)))
222
+ {
223
+ jQuery(this).attr('id', generateId(this));
224
+ }
225
+ ids.push(id);
226
+ });
227
+ return this;
228
+ },
229
+ /**
230
+ * Updates the TOC from the sections in the given context, or in
231
+ * all containers that have been registered with this TOC, if no
232
+ * context is given.
233
+ */
234
+ update: function ($ctx) {
235
+ var self = this;
236
+ $ctx = $ctx || self.$containers;
237
+ var outline = this.outline(self.$containers);
238
+ var ancestors = [self.root()];
239
+ var prevSiblings = [];
240
+ //TODO: handle TOC rebuilding more intelligently. currently,
241
+ //the TOC is always rebuilt from scratch.
242
+ last(ancestors).empty();
243
+ (function descend(outline) {
244
+ var prevSiblings = [];
245
+ each(outline, function (node) {
246
+ var $section = head(node);
247
+ var $entry = self.linkSection($section, ancestors, prevSiblings);
248
+ ancestors.push($entry);
249
+ descend(tail(node));
250
+ ancestors.pop();
251
+ prevSiblings.push($entry);
252
+ });
253
+ })(tail(outline));
254
+
255
+ // count number of li's in the TOC, if less than minEntries, hide the TOC
256
+ var minEntries = self.root().attr('data-TOC-minEntries') || this.settings.minEntries;
257
+ if (self.root().find('li').length >= minEntries) {
258
+ self.root().show();
259
+ } else {
260
+ self.root().hide();
261
+ }
262
+
263
+ return this;
264
+ },
265
+ /**
266
+ * updates or creates an entry in the TOC for the given section.
267
+ */
268
+ linkSection: function ($section, ancestors, prevSiblings) {
269
+ var linkId = $section.eq(0).attr('id');
270
+ if (!linkId) {
271
+ linkId = generateId($section.get(0));
272
+ $section.eq(0).attr('id', linkId);
273
+ }
274
+ var $root = this.root();
275
+ var $entry = anchorFromLinkId($root, linkId);
276
+ if (!$entry.length) {
277
+ $entry = jQuery('<li><a/></li>');
278
+ }
279
+ $entry.find('a').
280
+ attr('href', '#' + linkId).
281
+ text($section.eq(0).text());
282
+ if (last(prevSiblings)) {
283
+ last(prevSiblings).after($entry);
284
+ }
285
+ else {
286
+ if (last(ancestors).get(0) == $root.get(0)) {
287
+ $root.append($entry);
288
+ }
289
+ else {
290
+ var $subToc = jQuery('<ol/>').append($entry);
291
+ last(ancestors).append($subToc);
292
+ }
293
+ }
294
+ return $entry;
295
+ },
296
+
297
+ /**
298
+ * returns a tree of sections in the given context. if the context
299
+ * element(s) begin a section, they will be included. First element
300
+ * of each branch in the tree is a $(section) or $() for the
301
+ * root node.
302
+ * TODO: http://www.w3.org/TR/html5/sections.html#outline
303
+ */
304
+ outline: function (ctx) {
305
+ var rootNode = [jQuery()];
306
+ var potentialParents = [rootNode];
307
+ this.headings(ctx).each(function(){
308
+ var $heading = jQuery(this);
309
+ var nodeName = this.nodeName.toLowerCase();
310
+ var hLevels = ['h6', 'h5', 'h4', 'h3', 'h2', 'h1'];
311
+ var currLevel = jQuery.inArray(nodeName, hLevels);
312
+ var higherEq = hLevels.slice(currLevel).join(',');
313
+ var $section = $heading.nextUntil(higherEq).andSelf();
314
+ var node = [$section];
315
+
316
+ var parent = detect(potentialParents, function (parent) {
317
+ var parentSection = parent[0];
318
+ return !parentSection.length || //top-level contains everything
319
+ detect(parentSection, function (sectionElem) {
320
+ return $heading.get(0) === sectionElem ||
321
+ jQuery.contains(sectionElem, $heading.get(0));
322
+ });
323
+ });
324
+ parent.push(node);
325
+ potentialParents.splice(0, indexOf(potentialParents, parent), node);
326
+ });
327
+ return rootNode;
328
+ },
329
+
330
+ headings: function ($ctx) {
331
+ return $ctx.find(':header').add($ctx.filter(':header'));
332
+ }
333
+
334
+
335
+
336
+ }
337
+ }
338
+
339
+ });
340
+
341
+ //-------------- module methods -----------------
342
+
343
+ function editableContainers () {
344
+ return jQuery(map(Aloha.editables, function (editable) {
345
+ return document.getElementById(editable.getId());
346
+ }));
347
+ }
348
+
349
+ function anchorFromLinkId ($ctx, linkId) {
350
+ return linkId ? $ctx.find('a[href $= "#' + linkId + '"]') : jQuery();
351
+ }
352
+
353
+ function linkIdFromAnchor ($anchor){
354
+ var href = $anchor.attr('href');
355
+ return href ? href.match(/#(.*?)$/)[1] : null;
356
+ }
357
+
358
+ function generateId (elemOrText) {
359
+ var validId;
360
+ if (typeof elemOrText == "object") {
361
+ validId = jQuery(elemOrText).text().
362
+ replace(/[^a-zA-Z-]+/g, '-').
363
+ replace(/^[^a-zA-Z]+/, '');
364
+ } else if (elemOrText) {
365
+ validId = elemOrText;
366
+ }
367
+ for (var uniquifier = 0;; uniquifier++) {
368
+ var uniqueId = validId;
369
+ if (uniquifier) {
370
+ uniqueId += '-' + uniquifier;
371
+ }
372
+ var conflict = document.getElementById(uniqueId);
373
+ if ( !conflict
374
+ || ( typeof elemOrText == "object"
375
+ && conflict === elemOrText))
376
+ {
377
+ return uniqueId;
378
+ }
379
+ }
380
+ //unreachable
381
+ }
382
+ });