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
@@ -13608,14 +13608,38 @@ Ext.DomHelper = function(){
13608
13608
  setStart = 'setStart' + (endRe.test(where) ? 'After' : 'Before');
13609
13609
  if (hash[where]) {
13610
13610
  range[setStart](el);
13611
- frag = range.createContextualFragment(html);
13611
+
13612
+ // Workaround for IE9, because it does not have this method anymore
13613
+ // When we have moved to jQuery we won't need this anymore
13614
+ if (typeof range.createContextualFragment === 'function') {
13615
+ frag = range.createContextualFragment(html);
13616
+ }
13617
+ else {
13618
+ frag = document.createDocumentFragment(),
13619
+ div = document.createElement("div");
13620
+ frag.appendChild(div);
13621
+ div.outerHTML = html;
13622
+ }
13623
+
13612
13624
  el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);
13613
13625
  return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling'];
13614
13626
  } else {
13615
13627
  rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child';
13616
13628
  if (el.firstChild) {
13617
13629
  range[setStart](el[rangeEl]);
13618
- frag = range.createContextualFragment(html);
13630
+
13631
+ // Workaround for IE9, because it does not have this method anymore
13632
+ // When we have moved to jQuery we won't need this anymore
13633
+ if (typeof range.createContextualFragment === 'function') {
13634
+ frag = range.createContextualFragment(html);
13635
+ }
13636
+ else {
13637
+ frag = document.createDocumentFragment(),
13638
+ div = document.createElement("div");
13639
+ frag.appendChild(div);
13640
+ div.outerHTML = html;
13641
+ }
13642
+
13619
13643
  if(where == afterbegin){
13620
13644
  el.insertBefore(frag, el.firstChild);
13621
13645
  }else{
@@ -61125,7 +61149,17 @@ Ext.grid.GroupingView.GROUP_ID = 1000;
61125
61149
  */
61126
61150
 
61127
61151
  // define jquery and ext modules. They need to be available in global namespace
61128
- define('aloha/jquery',[], function() {
61152
+ define('aloha/jquery',[], function() {
61153
+ // Work-around for http://bugs.jquery.com/ticket/9905
61154
+ // and https://github.com/alohaeditor/Aloha-Editor/issues/397
61155
+ if ( !Aloha.jQuery.support.getSetAttribute ) {
61156
+ ( function( global ) {
61157
+ Aloha.jQuery.removeAttr = function( elem, name ) {
61158
+ elem.removeAttribute( name );
61159
+ };
61160
+ }( Aloha ));
61161
+ }
61162
+
61129
61163
  return Aloha.jQuery;
61130
61164
  });
61131
61165
 
@@ -61162,6 +61196,488 @@ define('aloha/ext',[], function() {
61162
61196
  return Ext;
61163
61197
  });
61164
61198
 
61199
+ /*
61200
+ http://www.JSON.org/json2.js
61201
+ 2011-02-23
61202
+
61203
+ Public Domain.
61204
+
61205
+ NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
61206
+
61207
+ See http://www.JSON.org/js.html
61208
+
61209
+
61210
+ This code should be minified before deployment.
61211
+ See http://javascript.crockford.com/jsmin.html
61212
+
61213
+ USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
61214
+ NOT CONTROL.
61215
+
61216
+
61217
+ This file creates a global JSON object containing two methods: stringify
61218
+ and parse.
61219
+
61220
+ JSON.stringify(value, replacer, space)
61221
+ value any JavaScript value, usually an object or array.
61222
+
61223
+ replacer an optional parameter that determines how object
61224
+ values are stringified for objects. It can be a
61225
+ function or an array of strings.
61226
+
61227
+ space an optional parameter that specifies the indentation
61228
+ of nested structures. If it is omitted, the text will
61229
+ be packed without extra whitespace. If it is a number,
61230
+ it will specify the number of spaces to indent at each
61231
+ level. If it is a string (such as '\t' or ' '),
61232
+ it contains the characters used to indent at each level.
61233
+
61234
+ This method produces a JSON text from a JavaScript value.
61235
+
61236
+ When an object value is found, if the object contains a toJSON
61237
+ method, its toJSON method will be called and the result will be
61238
+ stringified. A toJSON method does not serialize: it returns the
61239
+ value represented by the name/value pair that should be serialized,
61240
+ or undefined if nothing should be serialized. The toJSON method
61241
+ will be passed the key associated with the value, and this will be
61242
+ bound to the value
61243
+
61244
+ For example, this would serialize Dates as ISO strings.
61245
+
61246
+ Date.prototype.toJSON = function (key) {
61247
+ function f(n) {
61248
+ // Format integers to have at least two digits.
61249
+ return n < 10 ? '0' + n : n;
61250
+ }
61251
+
61252
+ return this.getUTCFullYear() + '-' +
61253
+ f(this.getUTCMonth() + 1) + '-' +
61254
+ f(this.getUTCDate()) + 'T' +
61255
+ f(this.getUTCHours()) + ':' +
61256
+ f(this.getUTCMinutes()) + ':' +
61257
+ f(this.getUTCSeconds()) + 'Z';
61258
+ };
61259
+
61260
+ You can provide an optional replacer method. It will be passed the
61261
+ key and value of each member, with this bound to the containing
61262
+ object. The value that is returned from your method will be
61263
+ serialized. If your method returns undefined, then the member will
61264
+ be excluded from the serialization.
61265
+
61266
+ If the replacer parameter is an array of strings, then it will be
61267
+ used to select the members to be serialized. It filters the results
61268
+ such that only members with keys listed in the replacer array are
61269
+ stringified.
61270
+
61271
+ Values that do not have JSON representations, such as undefined or
61272
+ functions, will not be serialized. Such values in objects will be
61273
+ dropped; in arrays they will be replaced with null. You can use
61274
+ a replacer function to replace those with JSON values.
61275
+ JSON.stringify(undefined) returns undefined.
61276
+
61277
+ The optional space parameter produces a stringification of the
61278
+ value that is filled with line breaks and indentation to make it
61279
+ easier to read.
61280
+
61281
+ If the space parameter is a non-empty string, then that string will
61282
+ be used for indentation. If the space parameter is a number, then
61283
+ the indentation will be that many spaces.
61284
+
61285
+ Example:
61286
+
61287
+ text = JSON.stringify(['e', {pluribus: 'unum'}]);
61288
+ // text is '["e",{"pluribus":"unum"}]'
61289
+
61290
+
61291
+ text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
61292
+ // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
61293
+
61294
+ text = JSON.stringify([new Date()], function (key, value) {
61295
+ return this[key] instanceof Date ?
61296
+ 'Date(' + this[key] + ')' : value;
61297
+ });
61298
+ // text is '["Date(---current time---)"]'
61299
+
61300
+
61301
+ JSON.parse(text, reviver)
61302
+ This method parses a JSON text to produce an object or array.
61303
+ It can throw a SyntaxError exception.
61304
+
61305
+ The optional reviver parameter is a function that can filter and
61306
+ transform the results. It receives each of the keys and values,
61307
+ and its return value is used instead of the original value.
61308
+ If it returns what it received, then the structure is not modified.
61309
+ If it returns undefined then the member is deleted.
61310
+
61311
+ Example:
61312
+
61313
+ // Parse the text. Values that look like ISO date strings will
61314
+ // be converted to Date objects.
61315
+
61316
+ myData = JSON.parse(text, function (key, value) {
61317
+ var a;
61318
+ if (typeof value === 'string') {
61319
+ a =
61320
+ /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
61321
+ if (a) {
61322
+ return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
61323
+ +a[5], +a[6]));
61324
+ }
61325
+ }
61326
+ return value;
61327
+ });
61328
+
61329
+ myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
61330
+ var d;
61331
+ if (typeof value === 'string' &&
61332
+ value.slice(0, 5) === 'Date(' &&
61333
+ value.slice(-1) === ')') {
61334
+ d = new Date(value.slice(5, -1));
61335
+ if (d) {
61336
+ return d;
61337
+ }
61338
+ }
61339
+ return value;
61340
+ });
61341
+
61342
+
61343
+ This is a reference implementation. You are free to copy, modify, or
61344
+ redistribute.
61345
+ */
61346
+
61347
+ /*jslint evil: true, strict: false, regexp: false */
61348
+
61349
+ /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
61350
+ call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
61351
+ getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
61352
+ lastIndex, length, parse, prototype, push, replace, slice, stringify,
61353
+ test, toJSON, toString, valueOf
61354
+ */
61355
+
61356
+
61357
+ // Create a JSON object only if one does not already exist. We create the
61358
+ // methods in a closure to avoid creating global variables.
61359
+ define( 'util/json2', [], function(){} );
61360
+
61361
+ var JSON;
61362
+ if (!JSON) {
61363
+ JSON = {};
61364
+ }
61365
+
61366
+ (function () {
61367
+
61368
+
61369
+ function f(n) {
61370
+ // Format integers to have at least two digits.
61371
+ return n < 10 ? '0' + n : n;
61372
+ }
61373
+
61374
+ if (typeof Date.prototype.toJSON !== 'function') {
61375
+
61376
+ Date.prototype.toJSON = function (key) {
61377
+
61378
+ return isFinite(this.valueOf()) ?
61379
+ this.getUTCFullYear() + '-' +
61380
+ f(this.getUTCMonth() + 1) + '-' +
61381
+ f(this.getUTCDate()) + 'T' +
61382
+ f(this.getUTCHours()) + ':' +
61383
+ f(this.getUTCMinutes()) + ':' +
61384
+ f(this.getUTCSeconds()) + 'Z' : null;
61385
+ };
61386
+
61387
+ String.prototype.toJSON =
61388
+ Number.prototype.toJSON =
61389
+ Boolean.prototype.toJSON = function (key) {
61390
+ return this.valueOf();
61391
+ };
61392
+ }
61393
+
61394
+ var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
61395
+ escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
61396
+ gap,
61397
+ indent,
61398
+ meta = { // table of character substitutions
61399
+ '\b': '\\b',
61400
+ '\t': '\\t',
61401
+ '\n': '\\n',
61402
+ '\f': '\\f',
61403
+ '\r': '\\r',
61404
+ '"' : '\\"',
61405
+ '\\': '\\\\'
61406
+ },
61407
+ rep;
61408
+
61409
+
61410
+ function quote(string) {
61411
+
61412
+ // If the string contains no control characters, no quote characters, and no
61413
+ // backslash characters, then we can safely slap some quotes around it.
61414
+ // Otherwise we must also replace the offending characters with safe escape
61415
+ // sequences.
61416
+
61417
+ escapable.lastIndex = 0;
61418
+ return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
61419
+ var c = meta[a];
61420
+ return typeof c === 'string' ? c :
61421
+ '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
61422
+ }) + '"' : '"' + string + '"';
61423
+ }
61424
+
61425
+
61426
+ function str(key, holder) {
61427
+
61428
+ // Produce a string from holder[key].
61429
+
61430
+ var i, // The loop counter.
61431
+ k, // The member key.
61432
+ v, // The member value.
61433
+ length,
61434
+ mind = gap,
61435
+ partial,
61436
+ value = holder[key];
61437
+
61438
+ // If the value has a toJSON method, call it to obtain a replacement value.
61439
+
61440
+ if (value && typeof value === 'object' &&
61441
+ typeof value.toJSON === 'function') {
61442
+ value = value.toJSON(key);
61443
+ }
61444
+
61445
+ // If we were called with a replacer function, then call the replacer to
61446
+ // obtain a replacement value.
61447
+
61448
+ if (typeof rep === 'function') {
61449
+ value = rep.call(holder, key, value);
61450
+ }
61451
+
61452
+ // What happens next depends on the value's type.
61453
+
61454
+ switch (typeof value) {
61455
+ case 'string':
61456
+ return quote(value);
61457
+
61458
+ case 'number':
61459
+
61460
+ // JSON numbers must be finite. Encode non-finite numbers as null.
61461
+
61462
+ return isFinite(value) ? String(value) : 'null';
61463
+
61464
+ case 'boolean':
61465
+ case 'null':
61466
+
61467
+ // If the value is a boolean or null, convert it to a string. Note:
61468
+ // typeof null does not produce 'null'. The case is included here in
61469
+ // the remote chance that this gets fixed someday.
61470
+
61471
+ return String(value);
61472
+
61473
+ // If the type is 'object', we might be dealing with an object or an array or
61474
+ // null.
61475
+
61476
+ case 'object':
61477
+
61478
+ // Due to a specification blunder in ECMAScript, typeof null is 'object',
61479
+ // so watch out for that case.
61480
+
61481
+ if (!value) {
61482
+ return 'null';
61483
+ }
61484
+
61485
+ // Make an array to hold the partial results of stringifying this object value.
61486
+
61487
+ gap += indent;
61488
+ partial = [];
61489
+
61490
+ // Is the value an array?
61491
+
61492
+ if (Object.prototype.toString.apply(value) === '[object Array]') {
61493
+
61494
+ // The value is an array. Stringify every element. Use null as a placeholder
61495
+ // for non-JSON values.
61496
+
61497
+ length = value.length;
61498
+ for (i = 0; i < length; i += 1) {
61499
+ partial[i] = str(i, value) || 'null';
61500
+ }
61501
+
61502
+ // Join all of the elements together, separated with commas, and wrap them in
61503
+ // brackets.
61504
+
61505
+ v = partial.length === 0 ? '[]' : gap ?
61506
+ '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
61507
+ '[' + partial.join(',') + ']';
61508
+ gap = mind;
61509
+ return v;
61510
+ }
61511
+
61512
+ // If the replacer is an array, use it to select the members to be stringified.
61513
+
61514
+ if (rep && typeof rep === 'object') {
61515
+ length = rep.length;
61516
+ for (i = 0; i < length; i += 1) {
61517
+ if (typeof rep[i] === 'string') {
61518
+ k = rep[i];
61519
+ v = str(k, value);
61520
+ if (v) {
61521
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
61522
+ }
61523
+ }
61524
+ }
61525
+ } else {
61526
+
61527
+ // Otherwise, iterate through all of the keys in the object.
61528
+
61529
+ for (k in value) {
61530
+ if (Object.prototype.hasOwnProperty.call(value, k)) {
61531
+ v = str(k, value);
61532
+ if (v) {
61533
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
61534
+ }
61535
+ }
61536
+ }
61537
+ }
61538
+
61539
+ // Join all of the member texts together, separated with commas,
61540
+ // and wrap them in braces.
61541
+
61542
+ v = partial.length === 0 ? '{}' : gap ?
61543
+ '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
61544
+ '{' + partial.join(',') + '}';
61545
+ gap = mind;
61546
+ return v;
61547
+ }
61548
+ }
61549
+
61550
+ // If the JSON object does not yet have a stringify method, give it one.
61551
+
61552
+ if (typeof JSON.stringify !== 'function') {
61553
+ JSON.stringify = function (value, replacer, space) {
61554
+
61555
+ // The stringify method takes a value and an optional replacer, and an optional
61556
+ // space parameter, and returns a JSON text. The replacer can be a function
61557
+ // that can replace values, or an array of strings that will select the keys.
61558
+ // A default replacer method can be provided. Use of the space parameter can
61559
+ // produce text that is more easily readable.
61560
+
61561
+ var i;
61562
+ gap = '';
61563
+ indent = '';
61564
+
61565
+ // If the space parameter is a number, make an indent string containing that
61566
+ // many spaces.
61567
+
61568
+ if (typeof space === 'number') {
61569
+ for (i = 0; i < space; i += 1) {
61570
+ indent += ' ';
61571
+ }
61572
+
61573
+ // If the space parameter is a string, it will be used as the indent string.
61574
+
61575
+ } else if (typeof space === 'string') {
61576
+ indent = space;
61577
+ }
61578
+
61579
+ // If there is a replacer, it must be a function or an array.
61580
+ // Otherwise, throw an error.
61581
+
61582
+ rep = replacer;
61583
+ if (replacer && typeof replacer !== 'function' &&
61584
+ (typeof replacer !== 'object' ||
61585
+ typeof replacer.length !== 'number')) {
61586
+ throw new Error('JSON.stringify');
61587
+ }
61588
+
61589
+ // Make a fake root object containing our value under the key of ''.
61590
+ // Return the result of stringifying the value.
61591
+
61592
+ return str('', {'': value});
61593
+ };
61594
+ }
61595
+
61596
+
61597
+ // If the JSON object does not yet have a parse method, give it one.
61598
+
61599
+ if (typeof JSON.parse !== 'function') {
61600
+ JSON.parse = function (text, reviver) {
61601
+
61602
+ // The parse method takes a text and an optional reviver function, and returns
61603
+ // a JavaScript value if the text is a valid JSON text.
61604
+
61605
+ var j;
61606
+
61607
+ function walk(holder, key) {
61608
+
61609
+ // The walk method is used to recursively walk the resulting structure so
61610
+ // that modifications can be made.
61611
+
61612
+ var k, v, value = holder[key];
61613
+ if (value && typeof value === 'object') {
61614
+ for (k in value) {
61615
+ if (Object.prototype.hasOwnProperty.call(value, k)) {
61616
+ v = walk(value, k);
61617
+ if (v !== undefined) {
61618
+ value[k] = v;
61619
+ } else {
61620
+ delete value[k];
61621
+ }
61622
+ }
61623
+ }
61624
+ }
61625
+ return reviver.call(holder, key, value);
61626
+ }
61627
+
61628
+
61629
+ // Parsing happens in four stages. In the first stage, we replace certain
61630
+ // Unicode characters with escape sequences. JavaScript handles many characters
61631
+ // incorrectly, either silently deleting them, or treating them as line endings.
61632
+
61633
+ text = String(text);
61634
+ cx.lastIndex = 0;
61635
+ if (cx.test(text)) {
61636
+ text = text.replace(cx, function (a) {
61637
+ return '\\u' +
61638
+ ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
61639
+ });
61640
+ }
61641
+
61642
+ // In the second stage, we run the text against regular expressions that look
61643
+ // for non-JSON patterns. We are especially concerned with '()' and 'new'
61644
+ // because they can cause invocation, and '=' because it can cause mutation.
61645
+ // But just to be safe, we want to reject all unexpected forms.
61646
+
61647
+ // We split the second stage into 4 regexp operations in order to work around
61648
+ // crippling inefficiencies in IE's and Safari's regexp engines. First we
61649
+ // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
61650
+ // replace all simple value tokens with ']' characters. Third, we delete all
61651
+ // open brackets that follow a colon or comma or that begin the text. Finally,
61652
+ // we look to see that the remaining characters are only whitespace or ']' or
61653
+ // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
61654
+
61655
+ if (/^[\],:{}\s]*$/
61656
+ .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
61657
+ .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
61658
+ .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
61659
+
61660
+ // In the third stage we use the eval function to compile the text into a
61661
+ // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
61662
+ // in JavaScript: it can begin a block or an object literal. We wrap the text
61663
+ // in parens to eliminate the ambiguity.
61664
+
61665
+ j = eval('(' + text + ')');
61666
+
61667
+ // In the optional fourth stage, we recursively walk the new structure, passing
61668
+ // each name/value pair to a reviver function for possible transformation.
61669
+
61670
+ return typeof reviver === 'function' ?
61671
+ walk({'': j}, '') : j;
61672
+ }
61673
+
61674
+ // If the text is not JSON parseable, then a SyntaxError is thrown.
61675
+
61676
+ throw new SyntaxError('JSON.parse');
61677
+ };
61678
+ }
61679
+ }());
61680
+
61165
61681
  define('vendor/jquery.json-2.2.min',['aloha/jquery'],
61166
61682
  function($) {$.toJSON=function(o)
61167
61683
  {if(typeof(JSON)=='object'&&JSON.stringify)
@@ -61230,9 +61746,9 @@ return'"'+string+'"';};var _escapeable=/["\\\x00-\x1f\x7f-\x9f]/g;var _meta={'\b
61230
61746
 
61231
61747
  define('vendor/jquery.store',[
61232
61748
  'aloha/jquery',
61233
- 'vendor/jquery.json-2.2.min'
61749
+ 'util/json2'
61234
61750
  ],
61235
- function($, _1, undefined) {
61751
+ function($, __unused_json, undefined) {
61236
61752
 
61237
61753
  /**********************************************************************************
61238
61754
  * $.store base and convinience accessor
@@ -61242,19 +61758,6 @@ $.store = function( driver, serializers )
61242
61758
  {
61243
61759
  var JSON = window.JSON
61244
61760
  that = this;
61245
-
61246
- // IE fix
61247
- if (typeof JSON === 'undefined' || !JSON) {
61248
- /*
61249
- * The GENTICS global namespace object. If GENTICS is already defined, the
61250
- * existing GENTICS object will not be overwritten so that defined
61251
- * namespaces are preserved.
61252
- */
61253
- var JSON = function () {
61254
- this.stringigy = function () {};
61255
- this.parse = function () {};
61256
- };
61257
- }
61258
61761
 
61259
61762
  if( typeof driver == 'string' )
61260
61763
  {
@@ -61639,6 +62142,43 @@ $.store.serializers = {
61639
62142
  }
61640
62143
  };
61641
62144
 
62145
+
62146
+ // We don't want to use window storage for ie7 with aloha because this causes massive issues when dealing with frames.
62147
+ // Window.name will change the framename and this will cause links with target attribute to stop working properly.
62148
+ // We remove the windowName driver and add the void driver which won't store any information.
62149
+ if ( $.browser.msie && $.browser.version == "7.0" ) {
62150
+ delete($.store.drivers.windowName);
62151
+ var voidDriver = {
62152
+ ident: "$.store.drivers.voidDriver",
62153
+ scope: 'void',
62154
+ cache: {},
62155
+ encodes: true,
62156
+ available: function()
62157
+ {
62158
+ return true;
62159
+ },
62160
+ init: function()
62161
+ {
62162
+ },
62163
+ save: function()
62164
+ {
62165
+ },
62166
+ get: function( key )
62167
+ {
62168
+ },
62169
+ set: function( key, value )
62170
+ {
62171
+ },
62172
+ del: function( key )
62173
+ {
62174
+ },
62175
+ flush: function()
62176
+ {
62177
+ }
62178
+ };
62179
+ $.store.drivers.voidDriver=voidDriver;
62180
+ }
62181
+
61642
62182
  });
61643
62183
 
61644
62184
  /**
@@ -64884,488 +65424,6 @@ rangy.createModule("DomUtil", function(api, module) {
64884
65424
  });
64885
65425
  });
64886
65426
 
64887
- /*
64888
- http://www.JSON.org/json2.js
64889
- 2011-02-23
64890
-
64891
- Public Domain.
64892
-
64893
- NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
64894
-
64895
- See http://www.JSON.org/js.html
64896
-
64897
-
64898
- This code should be minified before deployment.
64899
- See http://javascript.crockford.com/jsmin.html
64900
-
64901
- USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
64902
- NOT CONTROL.
64903
-
64904
-
64905
- This file creates a global JSON object containing two methods: stringify
64906
- and parse.
64907
-
64908
- JSON.stringify(value, replacer, space)
64909
- value any JavaScript value, usually an object or array.
64910
-
64911
- replacer an optional parameter that determines how object
64912
- values are stringified for objects. It can be a
64913
- function or an array of strings.
64914
-
64915
- space an optional parameter that specifies the indentation
64916
- of nested structures. If it is omitted, the text will
64917
- be packed without extra whitespace. If it is a number,
64918
- it will specify the number of spaces to indent at each
64919
- level. If it is a string (such as '\t' or '&nbsp;'),
64920
- it contains the characters used to indent at each level.
64921
-
64922
- This method produces a JSON text from a JavaScript value.
64923
-
64924
- When an object value is found, if the object contains a toJSON
64925
- method, its toJSON method will be called and the result will be
64926
- stringified. A toJSON method does not serialize: it returns the
64927
- value represented by the name/value pair that should be serialized,
64928
- or undefined if nothing should be serialized. The toJSON method
64929
- will be passed the key associated with the value, and this will be
64930
- bound to the value
64931
-
64932
- For example, this would serialize Dates as ISO strings.
64933
-
64934
- Date.prototype.toJSON = function (key) {
64935
- function f(n) {
64936
- // Format integers to have at least two digits.
64937
- return n < 10 ? '0' + n : n;
64938
- }
64939
-
64940
- return this.getUTCFullYear() + '-' +
64941
- f(this.getUTCMonth() + 1) + '-' +
64942
- f(this.getUTCDate()) + 'T' +
64943
- f(this.getUTCHours()) + ':' +
64944
- f(this.getUTCMinutes()) + ':' +
64945
- f(this.getUTCSeconds()) + 'Z';
64946
- };
64947
-
64948
- You can provide an optional replacer method. It will be passed the
64949
- key and value of each member, with this bound to the containing
64950
- object. The value that is returned from your method will be
64951
- serialized. If your method returns undefined, then the member will
64952
- be excluded from the serialization.
64953
-
64954
- If the replacer parameter is an array of strings, then it will be
64955
- used to select the members to be serialized. It filters the results
64956
- such that only members with keys listed in the replacer array are
64957
- stringified.
64958
-
64959
- Values that do not have JSON representations, such as undefined or
64960
- functions, will not be serialized. Such values in objects will be
64961
- dropped; in arrays they will be replaced with null. You can use
64962
- a replacer function to replace those with JSON values.
64963
- JSON.stringify(undefined) returns undefined.
64964
-
64965
- The optional space parameter produces a stringification of the
64966
- value that is filled with line breaks and indentation to make it
64967
- easier to read.
64968
-
64969
- If the space parameter is a non-empty string, then that string will
64970
- be used for indentation. If the space parameter is a number, then
64971
- the indentation will be that many spaces.
64972
-
64973
- Example:
64974
-
64975
- text = JSON.stringify(['e', {pluribus: 'unum'}]);
64976
- // text is '["e",{"pluribus":"unum"}]'
64977
-
64978
-
64979
- text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
64980
- // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
64981
-
64982
- text = JSON.stringify([new Date()], function (key, value) {
64983
- return this[key] instanceof Date ?
64984
- 'Date(' + this[key] + ')' : value;
64985
- });
64986
- // text is '["Date(---current time---)"]'
64987
-
64988
-
64989
- JSON.parse(text, reviver)
64990
- This method parses a JSON text to produce an object or array.
64991
- It can throw a SyntaxError exception.
64992
-
64993
- The optional reviver parameter is a function that can filter and
64994
- transform the results. It receives each of the keys and values,
64995
- and its return value is used instead of the original value.
64996
- If it returns what it received, then the structure is not modified.
64997
- If it returns undefined then the member is deleted.
64998
-
64999
- Example:
65000
-
65001
- // Parse the text. Values that look like ISO date strings will
65002
- // be converted to Date objects.
65003
-
65004
- myData = JSON.parse(text, function (key, value) {
65005
- var a;
65006
- if (typeof value === 'string') {
65007
- a =
65008
- /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
65009
- if (a) {
65010
- return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
65011
- +a[5], +a[6]));
65012
- }
65013
- }
65014
- return value;
65015
- });
65016
-
65017
- myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
65018
- var d;
65019
- if (typeof value === 'string' &&
65020
- value.slice(0, 5) === 'Date(' &&
65021
- value.slice(-1) === ')') {
65022
- d = new Date(value.slice(5, -1));
65023
- if (d) {
65024
- return d;
65025
- }
65026
- }
65027
- return value;
65028
- });
65029
-
65030
-
65031
- This is a reference implementation. You are free to copy, modify, or
65032
- redistribute.
65033
- */
65034
-
65035
- /*jslint evil: true, strict: false, regexp: false */
65036
-
65037
- /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
65038
- call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
65039
- getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
65040
- lastIndex, length, parse, prototype, push, replace, slice, stringify,
65041
- test, toJSON, toString, valueOf
65042
- */
65043
-
65044
-
65045
- // Create a JSON object only if one does not already exist. We create the
65046
- // methods in a closure to avoid creating global variables.
65047
- define( 'util/json2', [], function(){} );
65048
-
65049
- var JSON;
65050
- if (!JSON) {
65051
- JSON = {};
65052
- }
65053
-
65054
- (function () {
65055
-
65056
-
65057
- function f(n) {
65058
- // Format integers to have at least two digits.
65059
- return n < 10 ? '0' + n : n;
65060
- }
65061
-
65062
- if (typeof Date.prototype.toJSON !== 'function') {
65063
-
65064
- Date.prototype.toJSON = function (key) {
65065
-
65066
- return isFinite(this.valueOf()) ?
65067
- this.getUTCFullYear() + '-' +
65068
- f(this.getUTCMonth() + 1) + '-' +
65069
- f(this.getUTCDate()) + 'T' +
65070
- f(this.getUTCHours()) + ':' +
65071
- f(this.getUTCMinutes()) + ':' +
65072
- f(this.getUTCSeconds()) + 'Z' : null;
65073
- };
65074
-
65075
- String.prototype.toJSON =
65076
- Number.prototype.toJSON =
65077
- Boolean.prototype.toJSON = function (key) {
65078
- return this.valueOf();
65079
- };
65080
- }
65081
-
65082
- var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
65083
- escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
65084
- gap,
65085
- indent,
65086
- meta = { // table of character substitutions
65087
- '\b': '\\b',
65088
- '\t': '\\t',
65089
- '\n': '\\n',
65090
- '\f': '\\f',
65091
- '\r': '\\r',
65092
- '"' : '\\"',
65093
- '\\': '\\\\'
65094
- },
65095
- rep;
65096
-
65097
-
65098
- function quote(string) {
65099
-
65100
- // If the string contains no control characters, no quote characters, and no
65101
- // backslash characters, then we can safely slap some quotes around it.
65102
- // Otherwise we must also replace the offending characters with safe escape
65103
- // sequences.
65104
-
65105
- escapable.lastIndex = 0;
65106
- return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
65107
- var c = meta[a];
65108
- return typeof c === 'string' ? c :
65109
- '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
65110
- }) + '"' : '"' + string + '"';
65111
- }
65112
-
65113
-
65114
- function str(key, holder) {
65115
-
65116
- // Produce a string from holder[key].
65117
-
65118
- var i, // The loop counter.
65119
- k, // The member key.
65120
- v, // The member value.
65121
- length,
65122
- mind = gap,
65123
- partial,
65124
- value = holder[key];
65125
-
65126
- // If the value has a toJSON method, call it to obtain a replacement value.
65127
-
65128
- if (value && typeof value === 'object' &&
65129
- typeof value.toJSON === 'function') {
65130
- value = value.toJSON(key);
65131
- }
65132
-
65133
- // If we were called with a replacer function, then call the replacer to
65134
- // obtain a replacement value.
65135
-
65136
- if (typeof rep === 'function') {
65137
- value = rep.call(holder, key, value);
65138
- }
65139
-
65140
- // What happens next depends on the value's type.
65141
-
65142
- switch (typeof value) {
65143
- case 'string':
65144
- return quote(value);
65145
-
65146
- case 'number':
65147
-
65148
- // JSON numbers must be finite. Encode non-finite numbers as null.
65149
-
65150
- return isFinite(value) ? String(value) : 'null';
65151
-
65152
- case 'boolean':
65153
- case 'null':
65154
-
65155
- // If the value is a boolean or null, convert it to a string. Note:
65156
- // typeof null does not produce 'null'. The case is included here in
65157
- // the remote chance that this gets fixed someday.
65158
-
65159
- return String(value);
65160
-
65161
- // If the type is 'object', we might be dealing with an object or an array or
65162
- // null.
65163
-
65164
- case 'object':
65165
-
65166
- // Due to a specification blunder in ECMAScript, typeof null is 'object',
65167
- // so watch out for that case.
65168
-
65169
- if (!value) {
65170
- return 'null';
65171
- }
65172
-
65173
- // Make an array to hold the partial results of stringifying this object value.
65174
-
65175
- gap += indent;
65176
- partial = [];
65177
-
65178
- // Is the value an array?
65179
-
65180
- if (Object.prototype.toString.apply(value) === '[object Array]') {
65181
-
65182
- // The value is an array. Stringify every element. Use null as a placeholder
65183
- // for non-JSON values.
65184
-
65185
- length = value.length;
65186
- for (i = 0; i < length; i += 1) {
65187
- partial[i] = str(i, value) || 'null';
65188
- }
65189
-
65190
- // Join all of the elements together, separated with commas, and wrap them in
65191
- // brackets.
65192
-
65193
- v = partial.length === 0 ? '[]' : gap ?
65194
- '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
65195
- '[' + partial.join(',') + ']';
65196
- gap = mind;
65197
- return v;
65198
- }
65199
-
65200
- // If the replacer is an array, use it to select the members to be stringified.
65201
-
65202
- if (rep && typeof rep === 'object') {
65203
- length = rep.length;
65204
- for (i = 0; i < length; i += 1) {
65205
- if (typeof rep[i] === 'string') {
65206
- k = rep[i];
65207
- v = str(k, value);
65208
- if (v) {
65209
- partial.push(quote(k) + (gap ? ': ' : ':') + v);
65210
- }
65211
- }
65212
- }
65213
- } else {
65214
-
65215
- // Otherwise, iterate through all of the keys in the object.
65216
-
65217
- for (k in value) {
65218
- if (Object.prototype.hasOwnProperty.call(value, k)) {
65219
- v = str(k, value);
65220
- if (v) {
65221
- partial.push(quote(k) + (gap ? ': ' : ':') + v);
65222
- }
65223
- }
65224
- }
65225
- }
65226
-
65227
- // Join all of the member texts together, separated with commas,
65228
- // and wrap them in braces.
65229
-
65230
- v = partial.length === 0 ? '{}' : gap ?
65231
- '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
65232
- '{' + partial.join(',') + '}';
65233
- gap = mind;
65234
- return v;
65235
- }
65236
- }
65237
-
65238
- // If the JSON object does not yet have a stringify method, give it one.
65239
-
65240
- if (typeof JSON.stringify !== 'function') {
65241
- JSON.stringify = function (value, replacer, space) {
65242
-
65243
- // The stringify method takes a value and an optional replacer, and an optional
65244
- // space parameter, and returns a JSON text. The replacer can be a function
65245
- // that can replace values, or an array of strings that will select the keys.
65246
- // A default replacer method can be provided. Use of the space parameter can
65247
- // produce text that is more easily readable.
65248
-
65249
- var i;
65250
- gap = '';
65251
- indent = '';
65252
-
65253
- // If the space parameter is a number, make an indent string containing that
65254
- // many spaces.
65255
-
65256
- if (typeof space === 'number') {
65257
- for (i = 0; i < space; i += 1) {
65258
- indent += ' ';
65259
- }
65260
-
65261
- // If the space parameter is a string, it will be used as the indent string.
65262
-
65263
- } else if (typeof space === 'string') {
65264
- indent = space;
65265
- }
65266
-
65267
- // If there is a replacer, it must be a function or an array.
65268
- // Otherwise, throw an error.
65269
-
65270
- rep = replacer;
65271
- if (replacer && typeof replacer !== 'function' &&
65272
- (typeof replacer !== 'object' ||
65273
- typeof replacer.length !== 'number')) {
65274
- throw new Error('JSON.stringify');
65275
- }
65276
-
65277
- // Make a fake root object containing our value under the key of ''.
65278
- // Return the result of stringifying the value.
65279
-
65280
- return str('', {'': value});
65281
- };
65282
- }
65283
-
65284
-
65285
- // If the JSON object does not yet have a parse method, give it one.
65286
-
65287
- if (typeof JSON.parse !== 'function') {
65288
- JSON.parse = function (text, reviver) {
65289
-
65290
- // The parse method takes a text and an optional reviver function, and returns
65291
- // a JavaScript value if the text is a valid JSON text.
65292
-
65293
- var j;
65294
-
65295
- function walk(holder, key) {
65296
-
65297
- // The walk method is used to recursively walk the resulting structure so
65298
- // that modifications can be made.
65299
-
65300
- var k, v, value = holder[key];
65301
- if (value && typeof value === 'object') {
65302
- for (k in value) {
65303
- if (Object.prototype.hasOwnProperty.call(value, k)) {
65304
- v = walk(value, k);
65305
- if (v !== undefined) {
65306
- value[k] = v;
65307
- } else {
65308
- delete value[k];
65309
- }
65310
- }
65311
- }
65312
- }
65313
- return reviver.call(holder, key, value);
65314
- }
65315
-
65316
-
65317
- // Parsing happens in four stages. In the first stage, we replace certain
65318
- // Unicode characters with escape sequences. JavaScript handles many characters
65319
- // incorrectly, either silently deleting them, or treating them as line endings.
65320
-
65321
- text = String(text);
65322
- cx.lastIndex = 0;
65323
- if (cx.test(text)) {
65324
- text = text.replace(cx, function (a) {
65325
- return '\\u' +
65326
- ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
65327
- });
65328
- }
65329
-
65330
- // In the second stage, we run the text against regular expressions that look
65331
- // for non-JSON patterns. We are especially concerned with '()' and 'new'
65332
- // because they can cause invocation, and '=' because it can cause mutation.
65333
- // But just to be safe, we want to reject all unexpected forms.
65334
-
65335
- // We split the second stage into 4 regexp operations in order to work around
65336
- // crippling inefficiencies in IE's and Safari's regexp engines. First we
65337
- // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
65338
- // replace all simple value tokens with ']' characters. Third, we delete all
65339
- // open brackets that follow a colon or comma or that begin the text. Finally,
65340
- // we look to see that the remaining characters are only whitespace or ']' or
65341
- // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
65342
-
65343
- if (/^[\],:{}\s]*$/
65344
- .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
65345
- .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
65346
- .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
65347
-
65348
- // In the third stage we use the eval function to compile the text into a
65349
- // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
65350
- // in JavaScript: it can begin a block or an object literal. We wrap the text
65351
- // in parens to eliminate the ambiguity.
65352
-
65353
- j = eval('(' + text + ')');
65354
-
65355
- // In the optional fourth stage, we recursively walk the new structure, passing
65356
- // each name/value pair to a reviver function for possible transformation.
65357
-
65358
- return typeof reviver === 'function' ?
65359
- walk({'': j}, '') : j;
65360
- }
65361
-
65362
- // If the text is not JSON parseable, then a SyntaxError is thrown.
65363
-
65364
- throw new SyntaxError('JSON.parse');
65365
- };
65366
- }
65367
- }());
65368
-
65369
65427
  /* Simple JavaScript Inheritance
65370
65428
  * By John Resig http://ejohn.org/
65371
65429
  * MIT Licensed.
@@ -65512,9 +65570,21 @@ GENTICS.Utils.guid = function () {
65512
65570
 
65513
65571
  })(window);
65514
65572
 
65573
+ /**
65574
+ * ecma5schims.js - Shim for ECMA5 compatibility
65575
+ * (http://en.wikipedia.org/wiki/Shim_%28computing%29)
65576
+ *
65577
+ * A shim library that implements common functions that are missing on some
65578
+ * environments in order to complete ECMA5 compatibility across all major
65579
+ * browsers.
65580
+ *
65581
+ * TODO: This code needs to be refactored so as to conform to Aloha coding
65582
+ * standards. It is also severly lacking in documentation. Please take
65583
+ * note of: https://github.com/alohaeditor/Aloha-Editor/wiki/Commit-Checklist .
65584
+ */
65515
65585
 
65516
- define('aloha/ecma5shims',[],
65517
- function(){
65586
+ define('aloha/ecma5shims',[], function(){
65587
+
65518
65588
 
65519
65589
  var shims = {
65520
65590
  // Function bind
@@ -65750,12 +65820,16 @@ function(){
65750
65820
  if (node2 != useNode2) useNode2.parentNode.removeChild(useNode2);
65751
65821
  return result;
65752
65822
 
65753
-
65754
65823
  //node.ownerDocument gives the document object, which isn't the right info for a disconnect
65755
- function getRootParent(node) {
65756
- do { var parent = node; }
65757
- while (node = node.parentNode);
65758
- return parent;
65824
+ function getRootParent( node ) {
65825
+ var parent = null;
65826
+
65827
+ if ( node ) {
65828
+ do { parent = node; }
65829
+ while ( node = node.parentNode );
65830
+ }
65831
+
65832
+ return parent;
65759
65833
  }
65760
65834
 
65761
65835
  //Compare Position - MIT Licensed, John Resig; http://ejohn.org/blog/comparing-document-position/
@@ -65897,22 +65971,22 @@ var Dom = Class.extend({
65897
65971
  */
65898
65972
  tags: {
65899
65973
  'flow' : [ 'a', 'abbr', 'address', 'area', 'article', 'aside', 'audio',
65900
- 'b', 'bdo', 'blockquote', 'br', 'button', 'canvas', 'cite', 'code',
65974
+ 'b', 'bdi','bdo', 'blockquote', 'br', 'button', 'canvas', 'cite', 'code',
65901
65975
  'command', 'datalist', 'del', 'details', 'dfn', 'div', 'dl', 'em',
65902
65976
  'embed', 'fieldset', 'figure', 'footer', 'form', 'h1', 'h2', 'h3',
65903
65977
  'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'i', 'iframe', 'img',
65904
65978
  'input', 'ins', 'kbd', 'keygen', 'label', 'map', 'mark', 'math',
65905
65979
  'menu', 'meter', 'nav', 'noscript', 'object', 'ol', 'output', 'p',
65906
- 'pre', 'progress', 'q', 'ruby', 'samp', 'script', 'section',
65980
+ 'pre', 'progress', 'q', 'ruby', 's', 'samp', 'script', 'section',
65907
65981
  'select', 'small', 'span', 'strong', 'style', 'sub', 'sup', 'svg',
65908
- 'table', 'textarea', 'time', 'ul', 'var', 'video', 'wbr', '#text' ],
65909
- 'phrasing' : [ 'a', 'abbr', 'area', 'audio', 'b', 'bdo', 'br', 'button',
65982
+ 'table', 'textarea', 'time', 'u', 'ul', 'var', 'video', 'wbr', '#text' ],
65983
+ 'phrasing' : [ 'a', 'abbr', 'area', 'audio', 'b', 'bdi', 'bdo', 'br', 'button',
65910
65984
  'canvas', 'cite', 'code', 'command', 'datalist', 'del', 'dfn',
65911
65985
  'em', 'embed', 'i', 'iframe', 'img', 'input', 'ins', 'kbd',
65912
65986
  'keygen', 'label', 'map', 'mark', 'math', 'meter', 'noscript',
65913
65987
  'object', 'output', 'progress', 'q', 'ruby', 'samp', 'script',
65914
65988
  'select', 'small', 'span', 'strong', 'sub', 'sup', 'svg',
65915
- 'textarea', 'time', 'var', 'video', 'wbr', '#text' ]
65989
+ 'textarea', 'time', 'u', 'var', 'video', 'wbr', '#text' ]
65916
65990
  },
65917
65991
 
65918
65992
  /**
@@ -66025,6 +66099,7 @@ var Dom = Class.extend({
66025
66099
  'title' : '#text',
66026
66100
  'tr' : ['th', 'td'],
66027
66101
  'track' : 'empty',
66102
+ 'u' : 'phrasing',
66028
66103
  'ul' : 'li',
66029
66104
  'var' : 'phrasing',
66030
66105
  'video' : 'source', // transparent
@@ -66462,8 +66537,19 @@ var Dom = Class.extend({
66462
66537
 
66463
66538
  // iterate through all sub nodes
66464
66539
  startObject.contents().each(function(index) {
66540
+
66541
+ // Try to read the nodeType property and return if we do not have permission
66542
+ // ie.: frame document to an external URL
66543
+ var nodeType;
66544
+ try {
66545
+ nodeType = this.nodeType;
66546
+ }
66547
+ catch (e) {
66548
+ return;
66549
+ }
66550
+
66465
66551
  // decide further actions by node type
66466
- switch(this.nodeType) {
66552
+ switch(nodeType) {
66467
66553
  // found a non-text node
66468
66554
  case 1:
66469
66555
  if (prevNode && prevNode.nodeName == this.nodeName) {
@@ -67639,6 +67725,12 @@ define('aloha/core',[
67639
67725
  function ( jQuery, PluginManager ) {
67640
67726
 
67641
67727
 
67728
+ // Aloha Editor does not support Internet Explorer 6. ExtJS style fixes for
67729
+ // IE6 which are applied through the "ext-ie6" class cause visual bugs in
67730
+ // IE9, and so we remove it so that IE6 fixes are not applied.
67731
+ Aloha.ready(function() {
67732
+ jQuery('.ext-ie6').removeClass('ext-ie6');
67733
+ });
67642
67734
 
67643
67735
  //----------------------------------------
67644
67736
  // Private variables
@@ -67838,6 +67930,8 @@ function ( jQuery, PluginManager ) {
67838
67930
  * Fetches plugins the user wants to have loaded. Returns all plugins the user
67839
67931
  * has specified with the data-plugins property as array, with the bundle
67840
67932
  * name in front.
67933
+ * It's also possible to use 'Aloha.settings.plugins.load' to define the plugins
67934
+ * to load.
67841
67935
  *
67842
67936
  * @return array
67843
67937
  * @internal
@@ -67847,13 +67941,20 @@ function ( jQuery, PluginManager ) {
67847
67941
  var
67848
67942
  plugins = jQuery('[data-aloha-plugins]').data('aloha-plugins');
67849
67943
 
67944
+ // load aloha plugins from config
67945
+ if ( typeof Aloha.settings.plugins != 'undefined' && typeof Aloha.settings.plugins.load != 'undefined' ) {
67946
+ plugins = Aloha.settings.plugins.load;
67947
+ if (plugins instanceof Array) {
67948
+ return plugins;
67949
+ }
67950
+ }
67951
+
67850
67952
  // Determine Plugins
67851
67953
  if ( typeof plugins === 'string' && plugins !== "") {
67852
67954
  return plugins.replace(/\s+/g, '').split(',');
67853
67955
  }
67854
67956
  // Return
67855
67957
  return [];
67856
-
67857
67958
  },
67858
67959
 
67859
67960
  /**
@@ -68132,6 +68233,7 @@ function ( jQuery, PluginManager ) {
68132
68233
 
68133
68234
  /**
68134
68235
  * Determines the Aloha Url
68236
+ * Uses Aloha.settings.baseUrl if set.
68135
68237
  * @method
68136
68238
  * @return {String} alohaUrl
68137
68239
  */
@@ -68139,7 +68241,11 @@ function ( jQuery, PluginManager ) {
68139
68241
  // aloha base path is defined by a script tag with 2 data attributes
68140
68242
  var requireJs = jQuery('[data-aloha-plugins]'),
68141
68243
  baseUrl = ( requireJs.length ) ? requireJs[0].src.replace( /\/?aloha.js$/ , '' ) : '';
68142
-
68244
+
68245
+ if ( typeof Aloha.settings.baseUrl === "string" ) {
68246
+ baseUrl = Aloha.settings.baseUrl;
68247
+ }
68248
+
68143
68249
  return baseUrl;
68144
68250
  },
68145
68251
 
@@ -68169,7 +68275,6 @@ function ( jQuery, PluginManager ) {
68169
68275
 
68170
68276
  return Aloha;
68171
68277
  });
68172
-
68173
68278
  /*!
68174
68279
  * This file is part of Aloha Editor Project http://aloha-editor.org
68175
68280
  * Copyright © 2010-2011 Gentics Software GmbH, aloha@gentics.com
@@ -68640,7 +68745,6 @@ GENTICS.Utils.RangeObject = Class.extend({
68640
68745
  // sometimes it's cached (or was set)
68641
68746
  return this.commonAncestorContainer;
68642
68747
  }
68643
-
68644
68748
  // if it's not cached, calculate and then cache it
68645
68749
  this.updateCommonAncestorContainer();
68646
68750
 
@@ -68726,13 +68830,13 @@ GENTICS.Utils.RangeObject = Class.extend({
68726
68830
  * @hide
68727
68831
  */
68728
68832
  updateCommonAncestorContainer: function(commonAncestorContainer) {
68729
- // this will be needed either right now for finding the CAC or later for the crossing index
68730
- var parentsStartContainer = this.getStartContainerParents(),
68731
- parentsEndContainer = this.getEndContainerParents(),
68732
- i;
68733
-
68734
68833
  // if no parameter was passed, calculate it
68735
68834
  if (!commonAncestorContainer) {
68835
+ // this will be needed either right now for finding the CAC or later for the crossing index
68836
+ var parentsStartContainer = this.getStartContainerParents(),
68837
+ parentsEndContainer = this.getEndContainerParents(),
68838
+ i;
68839
+
68736
68840
  // find the crossing between startContainer and endContainer parents (=commonAncestorContainer)
68737
68841
  if (!(parentsStartContainer.length > 0 && parentsEndContainer.length > 0)) {
68738
68842
  console.warn('could not find commonAncestorContainer');
@@ -68913,6 +69017,7 @@ GENTICS.Utils.RangeObject = Class.extend({
68913
69017
  */
68914
69018
  update: function(event) {
68915
69019
  console.debug('now updating rangeObject');
69020
+
68916
69021
  this.initializeFromUserSelection(event);
68917
69022
  this.updateCommonAncestorContainer();
68918
69023
  },
@@ -69488,8 +69593,7 @@ function(Aloha, jQuery, Ext, Class, console) {
69488
69593
  getExtComponent: function () {
69489
69594
  var that = this;
69490
69595
 
69491
- if (typeof this.extPanel === 'undefined') {
69492
- // generate the panel here
69596
+ if (!this.extPanel) {
69493
69597
  this.extPanel = new Ext.Panel({
69494
69598
  'tbar' : [],
69495
69599
  'title' : this.label,
@@ -69497,13 +69601,15 @@ function(Aloha, jQuery, Ext, Class, console) {
69497
69601
  'bodyStyle': 'display:none',
69498
69602
  'autoScroll': true
69499
69603
  });
69604
+ }
69500
69605
 
69501
- // add the groups
69502
- jQuery.each(this.groups, function(index, group) {
69503
- // let each group generate its ext component and add them to the panel
69606
+ jQuery.each(this.groups, function(index, group) {
69607
+ // let each group generate its ext component and add them to
69608
+ // the panel once.
69609
+ if (!group.extButtonGroup) {
69504
69610
  that.extPanel.getTopToolbar().add(group.getExtComponent());
69505
- });
69506
- }
69611
+ }
69612
+ });
69507
69613
 
69508
69614
  return this.extPanel;
69509
69615
  },
@@ -69616,6 +69722,7 @@ function(Aloha, jQuery, Ext, Class, console) {
69616
69722
  'columns' : columnCount,
69617
69723
  'items': items
69618
69724
  });
69725
+
69619
69726
  // jQuery.each(this.fields, function(id, field){
69620
69727
  // that.buttons.push(field);
69621
69728
  // });
@@ -69689,6 +69796,73 @@ function(Aloha, jQuery, Ext, Class, console) {
69689
69796
  }
69690
69797
  });
69691
69798
 
69799
+ //=========================================================================
69800
+ //
69801
+ // Floating Menu
69802
+ //
69803
+ //=========================================================================
69804
+
69805
+ var lastFloatingMenuPos = {
69806
+ top: null,
69807
+ left: null
69808
+ };
69809
+
69810
+ /**
69811
+ * Handler for window scroll event. Positions the floating menu
69812
+ * appropriately.
69813
+ *
69814
+ * @param {Aloha.FloatingMenu} floatingmenu
69815
+ */
69816
+ function onWindowScroll( floatingmenu ) {
69817
+ if ( !Aloha.activeEditable ) {
69818
+ return;
69819
+ }
69820
+
69821
+ var element = floatingmenu.obj;
69822
+ var editablePos = Aloha.activeEditable.obj.offset();
69823
+ var isTopAligned = floatingmenu.behaviour === 'topalign';
69824
+ var isAppended = floatingmenu.behaviour === 'append';
69825
+ var isManuallyPinned = floatingmenu.pinned
69826
+ && ( parseInt( element.css( 'left' ), 10 )
69827
+ != ( editablePos.left
69828
+ + floatingmenu.horizontalOffset
69829
+ ) );
69830
+
69831
+ // no calculation when pinned manually or has behaviour 'append'
69832
+ if ( isTopAligned && isManuallyPinned || isAppended ) {
69833
+ return;
69834
+ }
69835
+
69836
+ var floatingmenuHeight = element.height();
69837
+ var scrollTop = jQuery( document ).scrollTop();
69838
+
69839
+ // This value is what the top position of the floating menu *would* be
69840
+ // if we tried to position it above the active editable.
69841
+ var floatingmenuTop = editablePos.top - floatingmenuHeight
69842
+ + floatingmenu.marginTop
69843
+ - floatingmenu.topalignOffset;
69844
+
69845
+ // The floating menu does not fit in the space between the top of the
69846
+ // viewport and the editable, so position it at the top of the viewport
69847
+ // and over the editable.
69848
+ if ( scrollTop > floatingmenuTop ) {
69849
+ editablePos.top = isTopAligned
69850
+ ? scrollTop + floatingmenu.marginTop
69851
+ : floatingmenu.marginTop;
69852
+
69853
+ // There is enough space on top of the editable to fit the entire
69854
+ // floating menu, so we do so.
69855
+ } else if ( scrollTop <= floatingmenuTop ) {
69856
+ editablePos.top -= floatingmenuHeight
69857
+ + ( isTopAligned
69858
+ ? floatingmenu.marginTop +
69859
+ floatingmenu.topalignOffset
69860
+ : 0 );
69861
+ }
69862
+
69863
+ floatingmenu.floatTo( editablePos );
69864
+ }
69865
+
69692
69866
  /**
69693
69867
  * Aloha's Floating Menu
69694
69868
  * @namespace Aloha
@@ -69768,16 +69942,30 @@ function(Aloha, jQuery, Ext, Class, console) {
69768
69942
  window: jQuery(window),
69769
69943
 
69770
69944
  /**
69771
- * define floating menu float behaviour. meant to be adjusted via
69772
- * GENTICS.Aloha.settings.floatingmenu.behaviour
69773
- * set it to 'float' for standard behaviour, or 'topalign' for a fixed fm
69945
+ * Aloha.settings.floatingmenu.behaviour
69946
+ *
69947
+ * Is used to define the floating menu (fm) float behaviour.
69948
+ *
69949
+ * available:
69950
+ * 'float' (default) the fm will float next to the position where the caret is,
69951
+ * 'topalign' the fm is fixed above the contentEditable which is active,
69952
+ * 'append' the fm is appended to the defined 'element' element position (top/left)
69774
69953
  */
69775
69954
  behaviour: 'float',
69776
69955
 
69956
+ /**
69957
+ * Aloha.settings.floatingmenu.element
69958
+ *
69959
+ * Is used to define the element where the floating menu is positioned when
69960
+ * Aloha.settings.floatingmenu.behaviour is set to 'append'
69961
+ *
69962
+ */
69963
+ element: 'floatingmenu',
69964
+
69777
69965
  /**
69778
69966
  * topalign offset to be used for topalign behavior
69779
69967
  */
69780
- topalignOffset: 90,
69968
+ topalignOffset: 0,
69781
69969
 
69782
69970
  /**
69783
69971
  * topalign offset to be used for topalign behavior
@@ -69788,7 +69976,7 @@ function(Aloha, jQuery, Ext, Class, console) {
69788
69976
  * will only be hounoured when behaviour is set to 'topalign'. Adds a margin,
69789
69977
  * so the floating menu is not directly attached to the top of the page
69790
69978
  */
69791
- marginTop: 0,
69979
+ marginTop: 10,
69792
69980
 
69793
69981
  /**
69794
69982
  * Define whether the floating menu shall be draggable or not via Aloha.settings.floatingmanu.draggable
@@ -69796,6 +69984,12 @@ function(Aloha, jQuery, Ext, Class, console) {
69796
69984
  */
69797
69985
  draggable: true,
69798
69986
 
69987
+ /**
69988
+ * Define whether the floating menu shall be pinned or not via Aloha.settings.floatingmanu.pin
69989
+ * Default is: false
69990
+ */
69991
+ pin: false,
69992
+
69799
69993
  /**
69800
69994
  * A list of all buttons that have been added to the floatingmenu
69801
69995
  * This needs to be tracked, as adding buttons twice will break the fm
@@ -69815,38 +70009,58 @@ function(Aloha, jQuery, Ext, Class, console) {
69815
70009
  init: function() {
69816
70010
 
69817
70011
  // check for behaviour setting of the floating menu
69818
- if (Aloha.settings.floatingmenu) {
69819
-
69820
- if (typeof Aloha.settings.floatingmenu.draggable === 'boolean') {
70012
+ if ( Aloha.settings.floatingmenu ) {
70013
+ if ( typeof Aloha.settings.floatingmenu.draggable ===
70014
+ 'boolean' ) {
69821
70015
  this.draggable = Aloha.settings.floatingmenu.draggable;
69822
70016
  }
69823
- if (typeof Aloha.settings.floatingmenu.behaviour === 'string') {
70017
+
70018
+ if ( typeof Aloha.settings.floatingmenu.behaviour ===
70019
+ 'string' ) {
69824
70020
  this.behaviour = Aloha.settings.floatingmenu.behaviour;
69825
70021
  }
69826
- if (typeof Aloha.settings.floatingmenu.topalignOffset !== 'undefined') {
69827
- this.topalignOffset = Aloha.settings.floatingmenu.topalignOffset;
70022
+
70023
+ if ( typeof Aloha.settings.floatingmenu.topalignOffset !==
70024
+ 'undefined' ) {
70025
+ this.topalignOffset = parseInt(
70026
+ Aloha.settings.floatingmenu.topalignOffset, 10 );
70027
+ }
70028
+
70029
+ if ( typeof Aloha.settings.floatingmenu.horizontalOffset !==
70030
+ 'undefined' ) {
70031
+ this.horizontalOffset = parseInt(
70032
+ Aloha.settings.floatingmenu.horizontalOffset , 10 );
69828
70033
  }
69829
- if (typeof Aloha.settings.floatingmenu.horizontalOffset !== 'undefined') {
69830
- this.horizontalOffset = Aloha.settings.floatingmenu.horizontalOffset;
70034
+
70035
+ if ( typeof Aloha.settings.floatingmenu.marginTop ===
70036
+ 'number' ) {
70037
+ this.marginTop = parseInt(
70038
+ Aloha.settings.floatingmenu.marginTop , 10 );
69831
70039
  }
69832
- if (typeof Aloha.settings.floatingmenu.marginTop === 'number') {
69833
- this.marginTop = Aloha.settings.floatingmenu.marginTop;
70040
+
70041
+ if ( typeof Aloha.settings.floatingmenu.element ===
70042
+ 'string' ) {
70043
+ this.element = Aloha.settings.floatingmenu.element;
69834
70044
  }
69835
- //We just check for undefined
69836
- if (typeof Aloha.settings.floatingmenu.width !== 'undefined') {
69837
- //Try to pars it
69838
- try {
69839
- var parsed = parseInt(Aloha.settings.floatingmenu.width);
69840
- this.width = Aloha.settings.floatingmenu.width;
69841
- } catch(e) {
69842
- //do nothing.
69843
- }
70045
+ if ( typeof Aloha.settings.floatingmenu.pin ===
70046
+ 'boolean' ) {
70047
+ this.pin = Aloha.settings.floatingmenu.pin;
70048
+ }
70049
+
70050
+
70051
+ if ( typeof Aloha.settings.floatingmenu.width !==
70052
+ 'undefined' ) {
70053
+ this.width = parseInt( Aloha.settings.floatingmenu.width,
70054
+ 10 );
69844
70055
  }
69845
70056
  }
69846
70057
 
69847
70058
  jQuery.storage = new jQuery.store();
70059
+
69848
70060
  this.currentScope = 'Aloha.global';
70061
+
69849
70062
  var that = this;
70063
+
69850
70064
  this.window.unload(function () {
69851
70065
  // store fm position if the panel is pinned to be able to restore it next time
69852
70066
  if (that.pinned) {
@@ -69886,7 +70100,7 @@ function(Aloha, jQuery, Ext, Class, console) {
69886
70100
  });
69887
70101
 
69888
70102
  if (typeof Aloha.settings.toolbar === 'object') {
69889
- this.fromConfig = true;
70103
+ this.fromConfig = true;
69890
70104
  }
69891
70105
  },
69892
70106
 
@@ -70004,6 +70218,10 @@ function(Aloha, jQuery, Ext, Class, console) {
70004
70218
  that.left = this.x;
70005
70219
  that.top = top;
70006
70220
 
70221
+ // store the last floating menu position when the floating menu was dragged around
70222
+ lastFloatingMenuPos.left = that.left;
70223
+ lastFloatingMenuPos.top = that.top;
70224
+
70007
70225
  this.panel.setPosition(this.x, top);
70008
70226
  that.refreshShadow();
70009
70227
  this.panel.shadow.show();
@@ -70054,8 +70272,10 @@ function(Aloha, jQuery, Ext, Class, console) {
70054
70272
  });
70055
70273
 
70056
70274
  // adapt the shadow
70057
- that.extTabPanel.shadow.show();
70058
- that.refreshShadow();
70275
+ if (that.extTabPanel.isVisible()) {
70276
+ that.extTabPanel.shadow.show();
70277
+ that.refreshShadow();
70278
+ }
70059
70279
  }
70060
70280
  }
70061
70281
  },
@@ -70064,6 +70284,7 @@ function(Aloha, jQuery, Ext, Class, console) {
70064
70284
 
70065
70285
 
70066
70286
  }
70287
+
70067
70288
  // add the tabs
70068
70289
  jQuery.each(this.tabs, function(index, tab) {
70069
70290
  // let each tab generate its ext component and add them to the panel
@@ -70075,8 +70296,10 @@ function(Aloha, jQuery, Ext, Class, console) {
70075
70296
  });
70076
70297
 
70077
70298
  // add the dropshadow
70078
- this.extTabPanel.shadow = jQuery('<div id="aloha-floatingmenu-shadow" class="aloha-shadow">&#160;</div>');
70079
- jQuery('body').append(this.extTabPanel.shadow);
70299
+ if (!this.extTabPanel.shadow) {
70300
+ this.extTabPanel.shadow = jQuery('<div id="aloha-floatingmenu-shadow" class="aloha-shadow">&#160;</div>').hide();
70301
+ jQuery('body').append(this.extTabPanel.shadow);
70302
+ }
70080
70303
 
70081
70304
  // add an empty pin tab item, store reference
70082
70305
  pinTab = this.extTabPanel.add({
@@ -70110,7 +70333,7 @@ function(Aloha, jQuery, Ext, Class, console) {
70110
70333
  this.obj = jQuery(this.extTabPanel.getEl().dom);
70111
70334
 
70112
70335
  if (jQuery.storage.get('Aloha.FloatingMenu.pinned') == 'true') {
70113
- this.togglePin();
70336
+ //this.togglePin();
70114
70337
 
70115
70338
  this.top = parseInt(jQuery.storage.get('Aloha.FloatingMenu.top'),10);
70116
70339
  this.left = parseInt(jQuery.storage.get('Aloha.FloatingMenu.left'),10);
@@ -70139,13 +70362,26 @@ function(Aloha, jQuery, Ext, Class, console) {
70139
70362
  this.obj.mousedown(function (e) {
70140
70363
  e.originalEvent.stopSelectionUpdate = true;
70141
70364
  Aloha.eventHandled = true;
70142
- // e.stopSelectionUpdate = true;
70365
+ //e.stopSelectionUpdate = true;
70143
70366
  });
70367
+
70144
70368
  this.obj.mouseup(function (e) {
70145
70369
  e.originalEvent.stopSelectionUpdate = true;
70146
70370
  Aloha.eventHandled = false;
70147
70371
  });
70148
70372
 
70373
+ jQuery( window ).scroll(function() {
70374
+ onWindowScroll( that );
70375
+ });
70376
+
70377
+ // don't display the drag handle bar / pin when floating menu is not draggable
70378
+ if ( !that.draggable ) {
70379
+ jQuery('.aloha-floatingmenu').hover( function() {
70380
+ jQuery(this).css({background: 'none'});
70381
+ jQuery('.aloha-floatingmenu-pin').hide();
70382
+ });
70383
+ }
70384
+
70149
70385
  // adjust float behaviour
70150
70386
  if (this.behaviour === 'float') {
70151
70387
  // listen to selectionChanged event
@@ -70157,56 +70393,85 @@ function(Aloha, jQuery, Ext, Class, console) {
70157
70393
  }
70158
70394
  }
70159
70395
  });
70160
- } else if (this.behaviour === 'topalign') {
70396
+ } else if (this.behaviour === 'append' ) {
70397
+ var p = jQuery( "#" + that.element );
70398
+ var position = p.offset();
70399
+
70400
+ if ( !position ) {
70401
+ Aloha.Log.warn(that, 'Invalid element HTML ID for floating menu: ' + that.element);
70402
+ return false;
70403
+ }
70404
+
70405
+ // set the position so that it does not float on the first editable activation
70406
+ this.floatTo( position );
70407
+
70408
+ if ( this.pin ) {
70409
+ this.togglePin( true );
70410
+ }
70411
+
70412
+ Aloha.bind( 'aloha-editable-activated', function( event, data ) {
70413
+ if ( that.pinned ) {
70414
+ return;
70415
+ }
70416
+ that.floatTo( position );
70417
+ });
70418
+
70419
+ } else if ( this.behaviour === 'topalign' ) {
70161
70420
  // topalign will retain the user's pinned status
70162
70421
  // TODO maybe the pin should be hidden in that case?
70163
- this.togglePin(false);
70164
-
70165
- // float the fm to each editable that is activated
70166
- Aloha.bind('aloha-editable-activated', function(event, data) {
70167
- var p = data.editable.obj.offset();
70168
- p.top -= that.topalignOffset;
70169
- p.left += that.horizontalOffset;
70170
- if (p.top < jQuery(document).scrollTop()) {
70171
- // scrollpos is below top of editable
70172
- that.obj.css('top', jQuery(document).scrollTop() + that.marginTop);
70173
- that.obj.css('left', p.left);
70174
- that.togglePin(true);
70175
- } else {
70176
- // scroll pos is above top of editable
70177
- that.floatTo(p);
70178
- }
70179
- });
70422
+ this.togglePin( false );
70180
70423
 
70181
- // fm scroll behaviour
70182
- jQuery(window).scroll(function () {
70183
- if (!Aloha.activeEditable) {
70184
- return;
70185
- }
70186
- var pos = Aloha.activeEditable.obj.offset(),
70187
- fmHeight = that.obj.height(),
70188
- scrollTop = jQuery(document).scrollTop();
70189
-
70190
- if (scrollTop > (pos.top - fmHeight - 6 - that.marginTop)) {
70191
- // scroll pos is lower than top of editable
70192
- that.togglePin(true);
70193
- that.obj.css('top', that.marginTop);
70194
- } else if (scrollTop <= (pos.top - fmHeight - 6 - that.marginTop)) {
70195
- // scroll pos is above top of editable
70196
- if (that.behaviour === 'topalign') {
70197
- pos.top = Aloha.activeEditable.obj.offset().top - that.topalignOffset;
70198
- pos.left = Aloha.activeEditable.obj.offset().left + that.horizontalOffset;
70424
+ // Float the menu to the editable that is activated.
70425
+ Aloha.bind( 'aloha-editable-activated', function( event, data ) {
70426
+ if ( that.pinned ) {
70427
+ return;
70428
+ }
70429
+
70430
+ // FIXME: that.obj.height() does not return the correct
70431
+ // height of the editable. We need to fix this, and
70432
+ // not hard-code the height as we currently do.
70433
+ var editable = data.editable.obj;
70434
+ var floatingmenuHeight = 90;
70435
+ var editablePos = editable.offset();
70436
+ var isFloatingmenuAboveViewport = ( (
70437
+ editablePos.top - floatingmenuHeight )
70438
+ < jQuery( document ).scrollTop() );
70439
+
70440
+ if ( isFloatingmenuAboveViewport ) {
70441
+ // Since we don't have space to place the floatingmenu
70442
+ // above the editable, we want to place it over the
70443
+ // editable instead. But if the editable is shorter
70444
+ // than the floatingmenu, it would be completely
70445
+ // covered by it, and so, in such cases, we position
70446
+ // the editable at the bottom of the short editable.
70447
+ editablePos.top = ( editable.height()
70448
+ < floatingmenuHeight )
70449
+ ? editablePos.top + editable.height()
70450
+ : jQuery( document ).scrollTop();
70451
+
70452
+ editablePos.top += that.marginTop;
70199
70453
  } else {
70200
- pos.top -= fmHeight + 6;
70454
+ editablePos.top -= floatingmenuHeight
70455
+ + that.topalignOffset;
70201
70456
  }
70202
- that.togglePin(false);
70203
- that.floatTo(pos);
70204
- } else if (scrollTop > pos.top + Aloha.activeEditable.obj.height() - fmHeight) {
70205
- // scroll pos is below editable
70206
- that.togglePin(false);
70207
- }
70208
- });
70209
- }
70457
+
70458
+ editablePos.left += that.horizontalOffset;
70459
+
70460
+ var HORIZONTAL_PADDING = 10;
70461
+ // Calculate by how much the floating menu is pocking
70462
+ // outside the width of the viewport. A positive number
70463
+ // means that it is outside the viewport, negative means
70464
+ // it is within the viewport.
70465
+ var overhang = ( ( editablePos.left + that.width
70466
+ + HORIZONTAL_PADDING ) - jQuery(window).width() );
70467
+
70468
+ if ( overhang > 0 ) {
70469
+ editablePos.left -= overhang;
70470
+ }
70471
+
70472
+ that.floatTo( editablePos );
70473
+ });
70474
+ }
70210
70475
  },
70211
70476
 
70212
70477
  /**
@@ -70385,6 +70650,11 @@ function(Aloha, jQuery, Ext, Class, console) {
70385
70650
  Aloha.Log.debug(this, 'doLayout called for FloatingMenu, scope is ' + this.currentScope);
70386
70651
  }
70387
70652
 
70653
+ // if there's no floatingmenu don't do anything
70654
+ if ( typeof this.extTabPanel === 'undefined' ) {
70655
+ return false;
70656
+ }
70657
+
70388
70658
  var that = this,
70389
70659
  firstVisibleTab = false,
70390
70660
  activeExtTab = this.extTabPanel.getActiveTab(),
@@ -70610,7 +70880,10 @@ function(Aloha, jQuery, Ext, Class, console) {
70610
70880
 
70611
70881
  // if the floating menu would be placed higher than the top of the screen...
70612
70882
  if ( top < scrollTop) {
70613
- top += 50 + GENTICS.Utils.Position.ScrollCorrection.top;
70883
+ top += 80 + GENTICS.Utils.Position.ScrollCorrection.top;
70884
+ // 80px if editable element is eg h1; 50px was fine for p;
70885
+ // todo: maybe just use GENTICS.Utils.Position.ScrollCorrection.top with a better value?
70886
+ // check where this is also used ...
70614
70887
  }
70615
70888
 
70616
70889
  // if the floating menu would float off the bottom of the screen
@@ -70644,24 +70917,47 @@ function(Aloha, jQuery, Ext, Class, console) {
70644
70917
  return;
70645
70918
  }
70646
70919
 
70647
- var that = this,
70648
- fmpos = this.obj.offset();
70920
+ var floatingmenu = this,
70921
+ fmpos = this.obj.offset(),
70922
+ lastLeft,
70923
+ lastTop;
70924
+
70925
+ if ( lastFloatingMenuPos.left === null ) {
70926
+ lastLeft = fmpos.left;
70927
+ lastTop = fmpos.top;
70928
+ } else {
70929
+ lastLeft = lastFloatingMenuPos.left;
70930
+ lastTop = lastFloatingMenuPos.top;
70931
+ }
70932
+
70933
+ // Place the floatingmenu to the last place the user had seen it,
70934
+ // then animate it into its new position.
70935
+ if ( lastLeft != position.left || lastTop != position.top ) {
70936
+ this.obj.offset({
70937
+ left: lastLeft,
70938
+ top: lastTop
70939
+ });
70649
70940
 
70650
- // move to the new position
70651
- if (fmpos.left != position.left || fmpos.top != position.top) {
70652
- this.obj.animate({
70653
- top: position.top,
70941
+ this.obj.animate( {
70942
+ top: position.top,
70654
70943
  left: position.left
70655
70944
  }, {
70656
70945
  queue : false,
70657
- step : function (step, props) {
70946
+ step : function( step, props ) {
70658
70947
  // update position reference
70659
- if (props.prop == 'top') {
70660
- that.top = props.now;
70661
- } else if (props.prop == 'left') {
70662
- that.left = props.now;
70948
+ if ( props.prop === 'top' ) {
70949
+ floatingmenu.top = props.now;
70950
+ } else if ( props.prop === 'left' ) {
70951
+ floatingmenu.left = props.now;
70663
70952
  }
70664
- that.refreshShadow(false);
70953
+
70954
+ floatingmenu.refreshShadow( false );
70955
+ },
70956
+ complete: function() {
70957
+ // When the animation is over, remember the floatingmenu's
70958
+ // final resting position.
70959
+ lastFloatingMenuPos.left = floatingmenu.left;
70960
+ lastFloatingMenuPos.top = floatingmenu.top;
70665
70961
  }
70666
70962
  });
70667
70963
  }
@@ -70727,6 +71023,7 @@ function(Aloha, jQuery, Ext, Class, console) {
70727
71023
  return menu;
70728
71024
  });
70729
71025
 
71026
+
70730
71027
  /*!
70731
71028
  * This file is part of Aloha Editor Project http://aloha-editor.org
70732
71029
  * Copyright (c) 2010-2011 Gentics Software GmbH, aloha@gentics.com
@@ -71080,8 +71377,18 @@ function(Aloha, jQuery, FloatingMenu, Class, Range) {
71080
71377
  // the start of the selection was not yet found, so look for it now
71081
71378
  // check whether the start of the selection is found here
71082
71379
 
71380
+ // Try to read the nodeType property and return if we do not have permission
71381
+ // ie.: frame document to an external URL
71382
+ var nodeType;
71383
+ try {
71384
+ nodeType = this.nodeType;
71385
+ }
71386
+ catch (e) {
71387
+ return;
71388
+ }
71389
+
71083
71390
  // check is dependent on the node type
71084
- switch(this.nodeType) {
71391
+ switch(nodeType) {
71085
71392
  case 3: // text node
71086
71393
  if (this === rangeObject.startContainer) {
71087
71394
  // the selection starts here
@@ -71331,8 +71638,17 @@ function(Aloha, jQuery, FloatingMenu, Class, Range) {
71331
71638
  standardAttributesComparator: function(domobj, markupObject) {
71332
71639
  var i, attr, classString, classes, classes2, classLength, attrLength, domAttrLength;
71333
71640
 
71641
+ // Cloning the domobj works around an IE7 bug that crashes
71642
+ // the browser. The exact place where IE7 crashes is when
71643
+ // the domobj.attribute[i] is read below.
71644
+ // The bug can be reproduced with an editable that contains
71645
+ // some text and and image, by clicking inside and outside the
71646
+ // editable a few times.
71647
+ domobj = domobj.cloneNode(false);
71648
+
71334
71649
  if (domobj.attributes && domobj.attributes.length && domobj.attributes.length > 0) {
71335
71650
  for (i = 0, domAttrLength = domobj.attributes.length; i < domAttrLength; i++) {
71651
+ // Dereferencing attributes[i] here would crash IE7 if domobj were not cloned above
71336
71652
  attr = domobj.attributes[i];
71337
71653
  if (attr.nodeName.toLowerCase() == 'class' && attr.nodeValue.length > 0) {
71338
71654
  classString = attr.nodeValue;
@@ -72830,12 +73146,224 @@ function correctRange ( range ) {
72830
73146
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
72831
73147
  */
72832
73148
 
72833
- define('aloha/markup',[ 'aloha/core', 'util/class', 'aloha/jquery' ],
72834
- function( Aloha, Class, jQuery ) {
73149
+ define('aloha/markup',[
73150
+ 'aloha/core',
73151
+ 'util/class',
73152
+ 'aloha/jquery',
73153
+ 'aloha/ecma5shims'
73154
+ ],
73155
+ function( Aloha, Class, jQuery, shims ) {
73156
+
72835
73157
 
72836
73158
 
72837
73159
  var GENTICS = window.GENTICS;
72838
73160
 
73161
+ var isOldIE = !!( jQuery.browser.msie &&
73162
+ 9 > parseInt( jQuery.browser.version, 10 ) );
73163
+
73164
+ function isBR( node ) {
73165
+ return 'BR' === node.nodeName;
73166
+ }
73167
+
73168
+ function isBlock( node ) {
73169
+ return 'false' === jQuery( node ).attr( 'contenteditable' );
73170
+ }
73171
+
73172
+ function isTextNode( node ) {
73173
+ return node && 3 === node.nodeType; // Node.TEXT_NODE
73174
+ }
73175
+
73176
+ function nodeLength( node ) {
73177
+ return !node ? 0
73178
+ : ( isTextNode( node ) ? node.length
73179
+ : node.childNodes.length );
73180
+ }
73181
+
73182
+ function nextVisibleNode( node ) {
73183
+ if ( !node ) {
73184
+ return null;
73185
+ }
73186
+
73187
+ if ( node.nextSibling ) {
73188
+ // Skip over nodes that the user cannot see ...
73189
+ if ( isTextNode( node.nextSibling ) &&
73190
+ !isVisibleTextNode( node.nextSibling ) ) {
73191
+ return nextVisibleNode( node.nextSibling );
73192
+ }
73193
+
73194
+ // Skip over propping <br>s ...
73195
+ if ( isBR( node.nextSibling ) &&
73196
+ node.nextSibling === node.parentNode.lastChild ) {
73197
+ return nextVisibleNode( node.nextSibling );
73198
+ }
73199
+
73200
+ // Skip over empty editable elements ...
73201
+ if ( '' === node.nextSibling.innerHTML &&
73202
+ !isBlock( node.nextSibling ) ) {
73203
+ return nextVisibleNode( node.nextSibling );
73204
+ }
73205
+
73206
+ return node.nextSibling;
73207
+ }
73208
+
73209
+ if ( node.parentNode ) {
73210
+ return nextVisibleNode( node.parentNode );
73211
+ }
73212
+
73213
+ return null;
73214
+ }
73215
+
73216
+ function prevVisibleNode( node ) {
73217
+ if ( !node ) {
73218
+ return null;
73219
+ }
73220
+
73221
+ if ( node.previousSibling ) {
73222
+ // Skip over nodes that the user cannot see...
73223
+ if ( isTextNode( node.previousSibling ) &&
73224
+ !isVisibleTextNode( node.previousSibling ) ) {
73225
+ return prevVisibleNode( node.previousSibling );
73226
+ }
73227
+
73228
+ // Skip over empty editable elements ...
73229
+ if ( '' === node.previousSibling.innerHTML &&
73230
+ !isBlock( node.previousSibling ) ) {
73231
+ return prevVisibleNode( node.previouSibling );
73232
+ }
73233
+
73234
+ return node.previousSibling;
73235
+ }
73236
+
73237
+ if ( node.parentNode ) {
73238
+ return prevVisibleNode( node.parentNode );
73239
+ }
73240
+
73241
+ return null;
73242
+ }
73243
+
73244
+ /**
73245
+ * Determines whether the given text node is visible to the the user,
73246
+ * based on our understanding that browsers will not display
73247
+ * superfluous white spaces.
73248
+ *
73249
+ * @param {HTMLEmenent} node The text node to be checked.
73250
+ */
73251
+ function isVisibleTextNode( node ) {
73252
+ return 0 < node.data.replace( /\s+/g, '' ).length;
73253
+ }
73254
+
73255
+ function isFrontPosition( node, offset ) {
73256
+ return ( 0 === offset ) ||
73257
+ ( offset <= node.data.length -
73258
+ node.data.replace( /^\s+/, '' ).length );
73259
+ }
73260
+
73261
+ function isBlockInsideEditable( $block ) {
73262
+ return $block.parent().hasClass( 'aloha-editable' );
73263
+ }
73264
+
73265
+ function isEndPosition( node, offset ) {
73266
+ var length = nodeLength( node );
73267
+
73268
+ if ( length === offset ) {
73269
+ return true;
73270
+ }
73271
+
73272
+ var isText = isTextNode( node );
73273
+
73274
+ // If within a text node, then ignore superfluous white-spaces,
73275
+ // since they are invisible to the user.
73276
+ if ( isText &&
73277
+ node.data.replace( /\s+$/, '' ).length === offset ) {
73278
+ return true;
73279
+ }
73280
+
73281
+ if ( 1 === length && !isText ) {
73282
+ return isBR( node.childNodes[0] );
73283
+ }
73284
+
73285
+ return false;
73286
+ }
73287
+
73288
+ function blink( node ) {
73289
+ jQuery( node )
73290
+ .stop( true )
73291
+ .css({ opacity: 0 })
73292
+ .fadeIn( 0 ).delay( 100 )
73293
+ .fadeIn(function () {
73294
+ jQuery( node ).css({ opacity: 1 });
73295
+ });
73296
+
73297
+ return node;
73298
+ }
73299
+
73300
+ /**
73301
+ * @TODO(petro): We need to be more intelligent about whether we insert a
73302
+ * block-level placeholder or a phrasing level element.
73303
+ * @TODO(petro): test with <pre>
73304
+ */
73305
+ function jumpBlock( block, isGoingLeft ) {
73306
+ var range = new GENTICS.Utils.RangeObject();
73307
+ var sibling = isGoingLeft ? prevVisibleNode( block )
73308
+ : nextVisibleNode( block );
73309
+
73310
+ if ( !sibling || isBlock( sibling ) ) {
73311
+ var $landing = jQuery( '<div>&nbsp;</div>' );
73312
+
73313
+ if ( isGoingLeft ) {
73314
+ jQuery( block ).before( $landing );
73315
+ } else {
73316
+ jQuery( block ).after( $landing );
73317
+ }
73318
+
73319
+ range.startContainer = range.endContainer = $landing[0];
73320
+ range.startOffset = range.endOffset = 0;
73321
+
73322
+ // Clear out any old placeholder first ...
73323
+ cleanupPlaceholders( range );
73324
+
73325
+ window.$_alohaPlaceholder = $landing;
73326
+ } else {
73327
+ range.startContainer = range.endContainer = sibling;
73328
+ range.startOffset = range.endOffset = isGoingLeft ?
73329
+ nodeLength( sibling ) : ( isOldIE ? 1 : 0 );
73330
+
73331
+ cleanupPlaceholders( range );
73332
+ }
73333
+
73334
+ range.select();
73335
+
73336
+ Aloha.trigger( 'aloha-block-selected', block );
73337
+ Aloha.Selection.preventSelectionChanged();
73338
+ }
73339
+
73340
+ function nodeContains( node1, node2 ) {
73341
+ return isOldIE ? ( shims.compareDocumentPosition( node1, node2 ) & 16 )
73342
+ : 0 < jQuery( node1 ).find( node2 ).length;
73343
+ }
73344
+
73345
+ function isInsidePlaceholder( range ) {
73346
+ var start = range.startContainer;
73347
+ var end = range.endContainer;
73348
+ var $placeholder = window.$_alohaPlaceholder;
73349
+
73350
+ return $placeholder.is( start ) ||
73351
+ $placeholder.is( end ) ||
73352
+ nodeContains( $placeholder[0], start ) ||
73353
+ nodeContains( $placeholder[0], end );
73354
+ }
73355
+
73356
+ function cleanupPlaceholders( range ) {
73357
+ if ( window.$_alohaPlaceholder && !isInsidePlaceholder( range ) ) {
73358
+ if ( 0 === window.$_alohaPlaceholder.html()
73359
+ .replace( /^(&nbsp;)*$/, '' ).length ) {
73360
+ window.$_alohaPlaceholder.remove();
73361
+ }
73362
+
73363
+ window.$_alohaPlaceholder = null;
73364
+ }
73365
+ }
73366
+
72839
73367
  /**
72840
73368
  * Markup object
72841
73369
  */
@@ -72917,9 +73445,14 @@ Aloha.Markup = Class.extend( {
72917
73445
  }
72918
73446
  }
72919
73447
 
72920
- // handle left (37) and right (39) keys for block detection
73448
+ // LEFT (37), RIGHT (39) keys for block detection
72921
73449
  if ( event.keyCode === 37 || event.keyCode === 39 ) {
72922
- return this.processCursor( rangeObject, event.keyCode );
73450
+ if ( this.processCursor( rangeObject, event.keyCode ) ) {
73451
+ cleanupPlaceholders( Aloha.Selection.rangeObject );
73452
+ return true;
73453
+ }
73454
+
73455
+ return false;
72923
73456
  }
72924
73457
 
72925
73458
  // BACKSPACE
@@ -72950,55 +73483,117 @@ Aloha.Markup = Class.extend( {
72950
73483
  },
72951
73484
 
72952
73485
  /**
72953
- * Processing of cursor keys
72954
- * will currently detect blocks (elements with contenteditable=false)
72955
- * and selects them (normally the cursor would jump right past them)
73486
+ * Processing of cursor keys.
73487
+ * Detect blocks (elements with contenteditable=false) and will select them
73488
+ * (normally the cursor would simply jump right past them).
72956
73489
  *
72957
- * For each block an 'aloha-block-selected' event will be triggered.
73490
+ * For each block that is selected, an 'aloha-block-selected' event will be
73491
+ * triggered.
72958
73492
  *
72959
- * @param range the current range object
72960
- * @param keyCode keyCode of current keypress
72961
- * @return false if a block was found to prevent further events, true otherwise
73493
+ * @param {RangyRange} range A range object for the current selection.
73494
+ * @param {number} keyCode Code of the currently pressed key.
73495
+ * @return {boolean} False if a block was found, to prevent further events,
73496
+ * true otherwise.
72962
73497
  */
72963
73498
  processCursor: function( range, keyCode ) {
72964
- var rt = range.getRangeTree(), // RangeTree reference
72965
- i = 0,
72966
- cursorLeft = keyCode === 37,
72967
- cursorRight = keyCode === 39,
72968
- nextSiblingIsBlock = false, // check whether the next sibling is a block (contenteditable = false)
72969
- cursorIsWithinBlock = false, // check whether the cursor is positioned within a block (contenteditable = false)
72970
- cursorAtLastPos = false, // check if the cursor is within the last position of the currently active dom element
72971
- obj; // will contain references to dom objects
72972
-
72973
73499
  if ( !range.isCollapsed() ) {
72974
73500
  return true;
72975
73501
  }
72976
73502
 
72977
- for ( ;i < rt.length; ++i ) {
72978
- if ( typeof rt[i].domobj === 'undefined'
72979
- || range.startOffset === rt[i].domobj.length ) {
72980
- continue;
72981
- }
73503
+ var node = range.startContainer;
72982
73504
 
72983
- nextSiblingIsBlock = jQuery( rt[i].domobj.nextSibling ).attr( 'contenteditable' ) === 'false';
72984
- cursorIsWithinBlock = jQuery( rt[i].domobj ).parents( '[contenteditable=false]' ).length > 0;
73505
+ if ( !node ) {
73506
+ return true;
73507
+ }
72985
73508
 
72986
- if ( cursorRight && nextSiblingIsBlock ) {
72987
- obj = rt[i].domobj.nextSibling;
72988
- GENTICS.Utils.Dom.selectDomNode( obj );
72989
- Aloha.trigger( 'aloha-block-selected', obj );
72990
- Aloha.Selection.preventSelectionChanged();
72991
- return false;
73509
+ var sibling;
73510
+
73511
+ // Versions of Internet Explorer that are older that 9, will
73512
+ // erroneously allow you to enter and edit inside elements which have
73513
+ // their contenteditable attribute set to false...
73514
+ if ( isOldIE ) {
73515
+ var $parentBlock = jQuery( node ).parents(
73516
+ '[contenteditable=false]' );
73517
+ var isInsideBlock = $parentBlock.length > 0;
73518
+
73519
+ if ( isInsideBlock ) {
73520
+ if ( isBlockInsideEditable( $parentBlock ) ) {
73521
+ sibling = $parentBlock[0];
73522
+ } else {
73523
+ return true;
73524
+ }
72992
73525
  }
73526
+ }
73527
+
73528
+ if ( !sibling ) {
73529
+ // True if keyCode denotes LEFT or UP arrow key, otherwise they
73530
+ // keyCode is for RIGHT or DOWN in which this value will be false.
73531
+ var isLeft = (37 === keyCode || 38 === keyCode);
73532
+ var offset = range.startOffset;
73533
+
73534
+ if ( isTextNode( node ) ) {
73535
+ if ( isLeft ) {
73536
+ // FIXME(Petro): Please consider if you have a better idea
73537
+ // of how we can work around this.
73538
+ //
73539
+ // Here is the problem... with Internet Explorer:
73540
+ // ----------------------------------------------
73541
+ //
73542
+ // Versions of Internet Explorer older than 9, are buggy in
73543
+ // how they `select()', or position a selection from cursor
73544
+ // movements, when the following conditions are true:
73545
+ //
73546
+ // * The range is collapsed.
73547
+ // * startContainer is a contenteditable text node.
73548
+ // * startOffset is 1.
73549
+ // * There is a non-conenteditable element left of the
73550
+ // startContainer.
73551
+ // * You attempt to move left to offset 0 (we consider a
73552
+ // range to be at "frontposition" if it is at offset 0
73553
+ // within its startContainer).
73554
+ //
73555
+ // What happens in IE 7, and IE 8, is that the selection
73556
+ // will jump to the adjacent non-contenteditable
73557
+ // element(s), instead moving to the front of the
73558
+ // container, and the offset will be stuck at 1--even as
73559
+ // the cursor is jumping around the screen!
73560
+ //
73561
+ // Our imperfect work-around is to reckon ourselves to be
73562
+ // at the front of the next node (ie: offset 0 in other
73563
+ // browsers), as soon as we detect that we are at offset 1
73564
+ // in IEv<9.
73565
+ //
73566
+ // Considering the bug, I think this is acceptable because
73567
+ // the user can still position themselve right between the
73568
+ // block (non-contenteditable element) and the first
73569
+ // characater of the text node by clicking there with the
73570
+ // mouse, since this seems to work fine in all IE versions.
73571
+ var isFrontPositionInIE = isOldIE && 1 === offset;
73572
+
73573
+ if ( !isFrontPositionInIE &&
73574
+ !isFrontPosition( node, offset ) ) {
73575
+ return true;
73576
+ }
72993
73577
 
72994
- if ( cursorLeft && cursorIsWithinBlock ) {
72995
- obj = jQuery( rt[i].domobj ).parents( '[contenteditable=false]' ).get( 0 );
72996
- GENTICS.Utils.Dom.selectDomNode( obj );
72997
- Aloha.trigger( 'aloha-block-selected', obj );
72998
- Aloha.Selection.preventSelectionChanged();
72999
- return false;
73578
+ } else if ( !isEndPosition( node, offset ) ) {
73579
+ return true;
73580
+ }
73581
+
73582
+ } else {
73583
+ node = node.childNodes[
73584
+ offset === nodeLength( node ) ? offset - 1 : offset ];
73000
73585
  }
73586
+
73587
+ sibling = isLeft ? prevVisibleNode( node )
73588
+ : nextVisibleNode( node );
73001
73589
  }
73590
+
73591
+ if ( isBlock( sibling ) ) {
73592
+ jumpBlock( sibling, isLeft );
73593
+ return false;
73594
+ }
73595
+
73596
+ return true;
73002
73597
  },
73003
73598
 
73004
73599
  /**
@@ -74068,6 +74663,12 @@ define('aloha/editable',[
74068
74663
  Aloha.settings.contentHandler = {};
74069
74664
  }
74070
74665
 
74666
+ var defaultContentSerializer = function(editableElement){
74667
+ return jQuery(editableElement).html();
74668
+ };
74669
+
74670
+ var contentSerializer = defaultContentSerializer;
74671
+
74071
74672
  /**
74072
74673
  * Editable object
74073
74674
  * @namespace Aloha
@@ -74092,8 +74693,9 @@ define('aloha/editable',[
74092
74693
 
74093
74694
  // delimiters, timer and idle for smartContentChange
74094
74695
  // smartContentChange triggers -- tab: '\u0009' - space: '\u0020' - enter: 'Enter'
74696
+ // backspace: U+0008 - delete: U+007F
74095
74697
  this.sccDelimiters = [ ':', ';', '.', '!', '?', ',',
74096
- unescape( '%u0009' ), unescape( '%u0020' ), 'Enter' ];
74698
+ unescape( '%u0009' ), unescape( '%u0020' ), unescape( '%u0008' ), unescape( '%u007F' ), 'Enter' ];
74097
74699
  this.sccIdle = 5000;
74098
74700
  this.sccDelay = 500;
74099
74701
  this.sccTimerIdle = false;
@@ -74216,8 +74818,13 @@ define('aloha/editable',[
74216
74818
  // if it does not handle the keyStroke it returns true and therefore all other
74217
74819
  // events (incl. browser's) continue
74218
74820
  me.obj.keydown( function( event ) {
74821
+ var letEventPass = Markup.preProcessKeyStrokes( event );
74219
74822
  me.keyCode = event.which;
74220
- return Markup.preProcessKeyStrokes( event );
74823
+ if (!letEventPass) {
74824
+ // the event will not proceed to key press, therefore trigger smartContentChange
74825
+ me.smartContentChange( event );
74826
+ }
74827
+ return letEventPass;
74221
74828
  } );
74222
74829
 
74223
74830
  // handle keypress
@@ -74704,19 +75311,32 @@ define('aloha/editable',[
74704
75311
  this.removePlaceholder( clonedObj );
74705
75312
  PluginManager.makeClean( clonedObj );
74706
75313
 
74707
- /*
74708
- //also deactivated for now. like initEditable. just in case ...
74709
- var content = clonedObj.html()
74710
- if ( typeof Aloha.settings.contentHandler.getContents === 'undefined' ) {
74711
- Aloha.settings.contentHandler.getContents = Aloha.defaults.contentHandler.getContents;
75314
+ return asObject ? clonedObj.contents() : contentSerializer(clonedObj[0]);
75315
+ },
75316
+
75317
+ /**
75318
+ * Set the contents of this editable as a HTML string
75319
+ * @param content as html
75320
+ * @param return as object or html string
75321
+ * @return contents of the editable
75322
+ */
75323
+ setContents: function( content, asObject ) {
75324
+ var reactivate = null;
75325
+
75326
+ if ( Aloha.getActiveEditable() === this ) {
75327
+ Aloha.deactivateEditable();
75328
+ reactivate = this;
74712
75329
  }
74713
- content = ContentHandlerManager.handleContent( content, {
74714
- contenthandler: Aloha.settings.contentHandler.getContents
74715
- } );
74716
- clonedObj.html( content );
74717
- */
74718
75330
 
74719
- return asObject ? clonedObj.contents() : clonedObj.html();
75331
+ this.obj.html( content );
75332
+
75333
+ if ( null !== reactivate ) {
75334
+ reactivate.activate();
75335
+ }
75336
+
75337
+ this.smartContentChange({type : 'set-contents'});
75338
+
75339
+ return asObject ? this.obj.contents() : contentSerializer(this.obj[0]);
74720
75340
  },
74721
75341
 
74722
75342
  /**
@@ -74865,8 +75485,26 @@ define('aloha/editable',[
74865
75485
  this.snapshotContent = this.getContents();
74866
75486
  return ret;
74867
75487
  }
74868
-
74869
75488
  } );
75489
+
75490
+ /**
75491
+ * Sets the serializer function to be used for the contents of all editables.
75492
+ *
75493
+ * The default content serializer will just call the jQuery.html()
75494
+ * function on the editable element (which gets the innerHTML property).
75495
+ *
75496
+ * This method is a static class method and will affect the result
75497
+ * of editable.getContents() for all editables that have been or
75498
+ * will be constructed.
75499
+ *
75500
+ * @param serializerFunction
75501
+ * A function that accepts a DOM element and returns the serialized
75502
+ * XHTML of the element contents (excluding the start and end tag of
75503
+ * the passed element).
75504
+ */
75505
+ Aloha.Editable.setContentSerializer = function( serializerFunction ) {
75506
+ contentSerializer = serializerFunction;
75507
+ };
74870
75508
  } );
74871
75509
 
74872
75510
  /*!
@@ -81512,6 +82150,7 @@ commands["delete"] = {
81512
82150
 
81513
82151
  // collapse whitespace sequences
81514
82152
  collapseWhitespace(node, range);
82153
+ offset = range.startOffset;
81515
82154
 
81516
82155
  // "If node is a Text node and offset is not zero, call collapse(node,
81517
82156
  // offset) on the Selection. Then delete the contents of the range with
@@ -82105,6 +82744,7 @@ commands.forwarddelete = {
82105
82744
 
82106
82745
  // collapse whitespace in the node, if it is a text node
82107
82746
  collapseWhitespace(node, range);
82747
+ offset = range.startOffset;
82108
82748
 
82109
82749
  // "If node is a Text node and offset is not node's length:"
82110
82750
  if (node.nodeType == $_.Node.TEXT_NODE
@@ -82901,11 +83541,13 @@ commands.insertparagraph = {
82901
83541
  // container name) on the context object."
82902
83542
  var newContainer = document.createElement(newContainerName);
82903
83543
 
82904
- // "Copy all attributes of container to new container."
82905
- for (var i = 0; i < container.attributes.length; i++) {
82906
- if (typeof newContainer.setAttributeNS === 'function') {
83544
+ // "Copy all non empty attributes of the container to new container."
83545
+ for ( var i = 0; i < container.attributes.length; i++ ) {
83546
+ if ( typeof newContainer.setAttributeNS === 'function' ) {
82907
83547
  newContainer.setAttributeNS(container.attributes[i].namespaceURI, container.attributes[i].name, container.attributes[i].value);
82908
- } else {
83548
+ } else if ( container.attributes[i].value.length > 0
83549
+ && container.attributes[i].value != 'null'
83550
+ && container.attributes[i].value > 0) {
82909
83551
  newContainer.setAttribute(container.attributes[i].name, container.attributes[i].value);
82910
83552
  }
82911
83553
  }
@@ -83564,7 +84206,6 @@ return {
83564
84206
  }
83565
84207
  }); // end define
83566
84208
  // vim: foldmarker=@{,@} foldmethod=marker
83567
-
83568
84209
  /*!
83569
84210
  * CommandManager file is part of Aloha Editor Project http://aloha-editor.org
83570
84211
  * Copyright (c) 2010-2011 Gentics Software GmbH, aloha@gentics.com
@@ -83653,19 +84294,22 @@ function( Aloha, Registry, Engine, Dom, ContentHandlerManager ) {
83653
84294
  }
83654
84295
 
83655
84296
  Engine.execCommand( commandId, showUi, value, range );
83656
-
83657
- // Read range after engine modification
83658
- range = Aloha.getSelection().getRangeAt( 0 );
83659
-
83660
- // FIX: doCleanup should work with W3C range
83661
- var startnode = range.commonAncestorContainer.parentNode;
83662
- var rangeObject = new window.GENTICS.Utils.RangeObject();
83663
- rangeObject.startContainer = range.startContainer;
83664
- rangeObject.startOffset = range.startOffset;
83665
- rangeObject.endContainer = range.endContainer;
83666
- rangeObject.endOffset = range.endOffset;
83667
- Dom.doCleanup({merge:true, removeempty: false}, rangeObject, startnode);
83668
- rangeObject.select();
84297
+
84298
+ if ( Aloha.getSelection().getRangeCount() ) {
84299
+ // Read range after engine modification
84300
+ range = Aloha.getSelection().getRangeAt( 0 );
84301
+
84302
+ // FIX: doCleanup should work with W3C range
84303
+ var startnode = range.commonAncestorContainer.parentNode;
84304
+ var rangeObject = new window.GENTICS.Utils.RangeObject();
84305
+ rangeObject.startContainer = range.startContainer;
84306
+ rangeObject.startOffset = range.startOffset;
84307
+ rangeObject.endContainer = range.endContainer;
84308
+ rangeObject.endOffset = range.endOffset;
84309
+ Dom.doCleanup({merge:true, removeempty: false}, rangeObject, startnode);
84310
+ rangeObject.select();
84311
+ }
84312
+
83669
84313
  Aloha.trigger('aloha-command-executed', commandId);
83670
84314
  },
83671
84315
 
@@ -84438,6 +85082,7 @@ define('aloha/sidebar',[
84438
85082
  sidebar.init( opts );
84439
85083
  }
84440
85084
  } );
85085
+
84441
85086
  };
84442
85087
 
84443
85088
  // ------------------------------------------------------------------------
@@ -84700,7 +85345,16 @@ define('aloha/sidebar',[
84700
85345
  if (this.opened) {
84701
85346
  this.rotateHandleArrow(isRight ? 0 : 180, 0);
84702
85347
  }
84703
-
85348
+
85349
+ // configure the position of the sidebar handle
85350
+ jQuery( function () {
85351
+ if ( typeof Aloha.settings.sidebar != 'undefined' &&
85352
+ Aloha.settings.sidebar.handle &&
85353
+ Aloha.settings.sidebar.handle.top ) {
85354
+ jQuery(bar.find(nsSel('handle'))).get(0).style.top = Aloha.settings.sidebar.handle.top;
85355
+ }
85356
+ } );
85357
+
84704
85358
  bar.find(nsSel('handle'))
84705
85359
  .click(function () {
84706
85360
  if (bounceTimer) {
@@ -85581,6 +86235,7 @@ define('aloha/repositorymanager',[
85581
86235
  Aloha.RepositoryManager = Class.extend( {
85582
86236
 
85583
86237
  repositories : [],
86238
+ settings: {},
85584
86239
 
85585
86240
  /**
85586
86241
  * Initialize all registered repositories
@@ -85597,15 +86252,15 @@ define('aloha/repositorymanager',[
85597
86252
  var repositories = this.repositories,
85598
86253
  i = 0,
85599
86254
  j = repositories.length,
85600
- repository,
85601
- settings;
86255
+ repository;
85602
86256
 
85603
86257
  if ( Aloha.settings && Aloha.settings.repositories ) {
85604
- settings = Aloha.settings.repositories;
85605
- } else {
85606
- settings = {};
86258
+ this.settings = Aloha.settings.repositories;
85607
86259
  }
85608
-
86260
+
86261
+ // use the configured repository manger query timeout or 5 sec
86262
+ this.settings.timeout = this.settings.timeout || 5000;
86263
+
85609
86264
  for ( ; i < j; ++i ) {
85610
86265
  repository = repositories[ i ];
85611
86266
 
@@ -85613,10 +86268,10 @@ define('aloha/repositorymanager',[
85613
86268
  repository.settings = {};
85614
86269
  }
85615
86270
 
85616
- if ( settings[ repository.repositoryId ] ) {
86271
+ if ( this.settings[ repository.repositoryId ] ) {
85617
86272
  jQuery.extend(
85618
86273
  repository.settings,
85619
- settings[ repository.repositoryId ]
86274
+ this.settings[ repository.repositoryId ]
85620
86275
  );
85621
86276
  }
85622
86277
 
@@ -85787,7 +86442,7 @@ define('aloha/repositorymanager',[
85787
86442
  // respond. 5 seconds is deemed to be the reasonable time to wait
85788
86443
  // when querying the repository manager in the context of something
85789
86444
  // like autocomplete
85790
- var timeout = parseInt( params.timeout, 10 ) || 5000;
86445
+ var timeout = parseInt( params.timeout, 10 ) || this.settings.timeout;
85791
86446
  timer = setTimeout( function() {
85792
86447
  numOpenCallbacks = 0;
85793
86448
  that.queryCallback( callback, allitems, allmetainfo, timer );
@@ -85951,7 +86606,7 @@ define('aloha/repositorymanager',[
85951
86606
  repositories = this.repositories;
85952
86607
  }
85953
86608
 
85954
- var timeout = parseInt( params.timeout, 10 ) || 5000;
86609
+ var timeout = parseInt( params.timeout, 10 ) || this.settings.timeout;
85955
86610
  timer = setTimeout( function() {
85956
86611
  numOpenCallbacks = 0;
85957
86612
  that.getChildrenCallback( callback, allitems, timer );
@@ -88703,6 +89358,7 @@ require(
88703
89358
  [
88704
89359
  'aloha/jquery',
88705
89360
  'aloha/ext',
89361
+ 'util/json2',
88706
89362
  ],
88707
89363
  function () {
88708
89364
  // load Aloha core files
@@ -88712,7 +89368,6 @@ require(
88712
89368
  'vendor/jquery.json-2.2.min',
88713
89369
  'vendor/jquery.store',
88714
89370
  'aloha/rangy-core',
88715
- 'util/json2',
88716
89371
  'util/class',
88717
89372
  'util/lang',
88718
89373
  'util/range',