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
@@ -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
+ });