wysihtml5x-rails 0.4.5 → 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0e9b69b5c919068f7b13f31518e2d94ad243e2c6
4
+ data.tar.gz: daa18493aca70d98cce1908d21b3a5f423e5aceb
5
+ SHA512:
6
+ metadata.gz: 785854013b0d44cbce92021376b6f0e87dd6b09bce62b63d39338eec816b2695ec55f397f319953dc08c935adb26e637e3b7a0e22780d241330d52cdd0fb726b
7
+ data.tar.gz: f7dee483d6aa30c6802aebbf25a448964be6979e0886cb5d1a7b7f9437e4cb1697aec655a320abec4ec106e9ffbd5b517d4fd21e2373f022128ea120dc895bea
@@ -1,5 +1,5 @@
1
1
  module Wysihtml5x
2
2
  module Rails
3
- VERSION = "0.4.5"
3
+ VERSION = "0.4.6"
4
4
  end
5
5
  end
@@ -77,6 +77,12 @@ var wysihtml5ParserRules = {
77
77
 
78
78
 
79
79
  "type_definitions": {
80
+
81
+ "visible_content_object": {
82
+ "methods": {
83
+ "has_visible_contet": 1
84
+ }
85
+ },
80
86
 
81
87
  "alignment_object": {
82
88
  "classes": {
@@ -344,7 +350,7 @@ var wysihtml5ParserRules = {
344
350
 
345
351
  "div": {
346
352
  "one_of_type": {
347
- "alignment_object": 1,
353
+ "visible_content_object": 1,
348
354
  },
349
355
  "remove_action": "unwrap",
350
356
  "keep_styles": {
@@ -25,7 +25,7 @@ if(!Array.isArray) {
25
25
  return Object.prototype.toString.call(arg) === '[object Array]';
26
26
  };
27
27
  };/**
28
- * @license wysihtml5x v0.4.5
28
+ * @license wysihtml5x v0.4.6
29
29
  * https://github.com/Edicy/wysihtml5
30
30
  *
31
31
  * Author: Christopher Blum (https://github.com/tiff)
@@ -36,7 +36,7 @@ if(!Array.isArray) {
36
36
  *
37
37
  */
38
38
  var wysihtml5 = {
39
- version: "0.4.5",
39
+ version: "0.4.6",
40
40
 
41
41
  // namespaces
42
42
  commands: {},
@@ -5362,74 +5362,22 @@ wysihtml5.dom.getParentElement = (function() {
5362
5362
  return styles[styles.length - 1] === cssStyle;
5363
5363
  }
5364
5364
 
5365
- function _getParentElementWithNodeName(node, nodeName, levels) {
5366
- while (levels-- && node && node.nodeName !== "BODY") {
5367
- if (_isSameNodeName(node.nodeName, nodeName)) {
5368
- return node;
5369
- }
5370
- node = node.parentNode;
5371
- }
5372
- return null;
5373
- }
5365
+ return function(node, matchingSet, levels, container) {
5366
+ var findByStyle = (matchingSet.cssStyle || matchingSet.styleRegExp),
5367
+ findByClass = (matchingSet.className || matchingSet.classRegExp);
5374
5368
 
5375
- function _getParentElementWithNodeNameAndClassName(node, nodeName, className, classRegExp, levels) {
5376
- while (levels-- && node && node.nodeName !== "BODY") {
5377
- if (_isElement(node) &&
5378
- _isSameNodeName(node.nodeName, nodeName) &&
5379
- _hasClassName(node, className, classRegExp)) {
5380
- return node;
5381
- }
5382
- node = node.parentNode;
5383
- }
5384
- return null;
5385
- }
5386
-
5387
- function _getParentElementWithNodeNameAndStyle(node, nodeName, cssStyle, styleRegExp, levels) {
5388
- while (levels-- && node && node.nodeName !== "BODY") {
5389
- if (_isElement(node) &&
5390
- _isSameNodeName(node.nodeName, nodeName) &&
5391
- _hasStyle(node, cssStyle, styleRegExp)
5392
- ) {
5393
- return node;
5394
- }
5395
- node = node.parentNode;
5396
- }
5397
- return null;
5398
- }
5369
+ levels = levels || 50; // Go max 50 nodes upwards from current node
5399
5370
 
5400
- function _getParentElementWithNodeNameAndClassNameAndStyle(node, nodeName, className, classRegExp, cssStyle, styleRegExp, levels) {
5401
- while (levels-- && node && node.nodeName !== "BODY") {
5402
- if (_isElement(node) &&
5403
- _isSameNodeName(node.nodeName, nodeName) &&
5404
- _hasStyle(node, cssStyle, styleRegExp) &&
5405
- _hasClassName(node, className, classRegExp)
5371
+ while (levels-- && node && node.nodeName !== "BODY" && (!container || node !== container)) {
5372
+ if (_isElement(node) && _isSameNodeName(node.nodeName, matchingSet.nodeName) &&
5373
+ (!findByStyle || _hasStyle(node, matchingSet.cssStyle, matchingSet.styleRegExp)) &&
5374
+ (!findByClass || _hasClassName(node, matchingSet.className, matchingSet.classRegExp))
5406
5375
  ) {
5407
5376
  return node;
5408
5377
  }
5409
5378
  node = node.parentNode;
5410
5379
  }
5411
5380
  return null;
5412
- }
5413
-
5414
- return function(node, matchingSet, levels) {
5415
- levels = levels || 50; // Go max 50 nodes upwards from current node
5416
- if ((matchingSet.className || matchingSet.classRegExp) && (matchingSet.cssStyle || matchingSet.styleRegExp)) {
5417
- return _getParentElementWithNodeNameAndClassNameAndStyle(
5418
- node, matchingSet.nodeName, matchingSet.className, matchingSet.classRegExp, matchingSet.cssStyle, matchingSet.styleRegExp, levels
5419
- );
5420
- } else if (matchingSet.className || matchingSet.classRegExp) {
5421
- return _getParentElementWithNodeNameAndClassName(
5422
- node, matchingSet.nodeName, matchingSet.className, matchingSet.classRegExp, levels
5423
- );
5424
- } else if (matchingSet.cssStyle || matchingSet.styleRegExp) {
5425
- return _getParentElementWithNodeNameAndStyle(
5426
- node, matchingSet.nodeName, matchingSet.cssStyle, matchingSet.styleRegExp, levels
5427
- );
5428
- } else {
5429
- return _getParentElementWithNodeName(
5430
- node, matchingSet.nodeName, levels
5431
- );
5432
- }
5433
5381
  };
5434
5382
  })();
5435
5383
  ;wysihtml5.dom.getNextElement = function(node){
@@ -5885,7 +5833,6 @@ wysihtml5.dom.parse = (function() {
5885
5833
  nodeName = oldNode.nodeName.toLowerCase(),
5886
5834
  scopeName = oldNode.scopeName;
5887
5835
 
5888
-
5889
5836
  /**
5890
5837
  * We already parsed that element
5891
5838
  * ignore it! (yes, this sometimes happens in IE8 when the html is invalid)
@@ -5940,7 +5887,7 @@ wysihtml5.dom.parse = (function() {
5940
5887
  _handleAttributes(oldNode, newNode, rule);
5941
5888
  _handleStyles(oldNode, newNode, rule);
5942
5889
  // tests if type condition is met or node should be removed/unwrapped
5943
- if (rule.one_of_type && !_testTypes(newNode, currentRules, rule.one_of_type)) {
5890
+ if (rule.one_of_type && !_testTypes(oldNode, currentRules, rule.one_of_type)) {
5944
5891
  return (rule.remove_action && rule.remove_action == "unwrap") ? false : null;
5945
5892
  }
5946
5893
 
@@ -5985,6 +5932,18 @@ wysihtml5.dom.parse = (function() {
5985
5932
  nodeStyles = oldNode.getAttribute("style"),
5986
5933
  classesLength, s, s_corrected, a, attr, currentClass, styleProp;
5987
5934
 
5935
+ // test for methods
5936
+ if (definition.methods) {
5937
+ for (var m in definition.methods) {
5938
+ if (definition.methods.hasOwnProperty(m) && typeCeckMethods[m]) {
5939
+
5940
+ if (typeCeckMethods[m](oldNode)) {
5941
+ return true;
5942
+ }
5943
+ }
5944
+ }
5945
+ }
5946
+
5988
5947
  // test for classes, if one found return true
5989
5948
  if (nodeClasses && definition.classes) {
5990
5949
  nodeClasses = nodeClasses.replace(/^\s+/g, '').replace(/\s+$/g, '').split(WHITE_SPACE_REG_EXP);
@@ -6364,6 +6323,40 @@ wysihtml5.dom.parse = (function() {
6364
6323
  })()
6365
6324
  };
6366
6325
 
6326
+ // checks if element is possibly visible
6327
+ var typeCeckMethods = {
6328
+ has_visible_contet: (function() {
6329
+ var txt,
6330
+ isVisible = false,
6331
+ visibleElements = ['img', 'video', 'picture', 'br', 'script', 'noscript',
6332
+ 'style', 'table', 'iframe', 'object', 'embed', 'audio',
6333
+ 'svg', 'input', 'button', 'select','textarea', 'canvas'];
6334
+
6335
+ return function(el) {
6336
+
6337
+ // has visible innertext. so is visible
6338
+ txt = (el.innerText || el.textContent).replace(/\s/g, '');
6339
+ if (txt && txt.length > 0) {
6340
+ return true;
6341
+ }
6342
+
6343
+ // matches list of visible dimensioned elements
6344
+ for (var i = visibleElements.length; i--;) {
6345
+ if (el.querySelector(visibleElements[i])) {
6346
+ return true;
6347
+ }
6348
+ }
6349
+
6350
+ // try to measure dimesions in last resort. (can find only of elements in dom)
6351
+ if (el.offsetWidth && el.offsetWidth > 0 && el.offsetHeight && el.offsetHeight > 0) {
6352
+ return true;
6353
+ }
6354
+
6355
+ return false;
6356
+ };
6357
+ })()
6358
+ };
6359
+
6367
6360
  return parse;
6368
6361
  })();
6369
6362
  ;/**
@@ -8555,6 +8548,19 @@ wysihtml5.quirks.ensureProperClearing = (function() {
8555
8548
  return (ret !== this.contain) ? ret : false;
8556
8549
  },
8557
8550
 
8551
+ getSelectionParentsByTag: function(tagName) {
8552
+ var nodes = this.getSelectedOwnNodes(),
8553
+ curEl, parents = [];
8554
+
8555
+ for (var i = 0, maxi = nodes.length; i < maxi; i++) {
8556
+ curEl = (nodes[i].nodeName && nodes[i].nodeName === 'LI') ? nodes[i] : wysihtml5.dom.getParentElement(nodes[i], { nodeName: ['LI']}, false, this.contain);
8557
+ if (curEl) {
8558
+ parents.push(curEl);
8559
+ }
8560
+ }
8561
+ return (parents.length) ? parents : null;
8562
+ },
8563
+
8558
8564
  getRangeToNodeEnd: function() {
8559
8565
  if (this.isCollapsed()) {
8560
8566
  var range = this.getRange(),
@@ -9606,6 +9612,7 @@ wysihtml5.quirks.ensureProperClearing = (function() {
9606
9612
  ancestor, styleAncestor, textNodes;
9607
9613
 
9608
9614
  for (var ri = range.length; ri--;) {
9615
+
9609
9616
  textNodes = range[ri].getNodes([wysihtml5.TEXT_NODE]);
9610
9617
  if (!textNodes.length) {
9611
9618
  ancestor = this.getAncestorWithClass(range[ri].startContainer);
@@ -9621,10 +9628,11 @@ wysihtml5.quirks.ensureProperClearing = (function() {
9621
9628
  if (!ancestor) {
9622
9629
  ancestor = this.getAncestorWithStyle(textNodes[i]);
9623
9630
  }
9624
- if (!(selectedText != "" && !ancestor)) {
9631
+ if (ancestor && selectedText != "") {
9625
9632
  ancestors.push(ancestor);
9626
9633
  }
9627
9634
  }
9635
+
9628
9636
  }
9629
9637
 
9630
9638
  return (ancestors.length) ? ancestors : false;
@@ -10461,13 +10469,19 @@ wysihtml5.commands.formatCode = {
10461
10469
  }
10462
10470
 
10463
10471
  function _getApplier(tagName, className, classRegExp, cssStyle, styleRegExp, container) {
10464
- var identifier = tagName + ":" + className;
10472
+ var identifier = tagName;
10473
+
10474
+ if (className) {
10475
+ identifier += ":" + className;
10476
+ }
10465
10477
  if (cssStyle) {
10466
10478
  identifier += ":" + cssStyle;
10467
10479
  }
10480
+
10468
10481
  if (!htmlApplier[identifier]) {
10469
10482
  htmlApplier[identifier] = new wysihtml5.selection.HTMLApplier(_getTagNames(tagName), className, classRegExp, true, cssStyle, styleRegExp, container);
10470
10483
  }
10484
+
10471
10485
  return htmlApplier[identifier];
10472
10486
  }
10473
10487
 
@@ -10546,7 +10560,7 @@ wysihtml5.commands.formatCode = {
10546
10560
 
10547
10561
  ownRanges = composer.selection.getOwnRanges();
10548
10562
 
10549
- if (ownRanges.length == 0) {
10563
+ if (!ownRanges || ownRanges.length === 0) {
10550
10564
  return false;
10551
10565
  }
10552
10566
 
@@ -11082,7 +11096,125 @@ wysihtml5.commands.formatCode = {
11082
11096
  return false;
11083
11097
  }
11084
11098
  };
11085
- ;/**
11099
+ ;wysihtml5.commands.indentList = {
11100
+ exec: function(composer, command, value) {
11101
+ var listEls = composer.selection.getSelectionParentsByTag('LI');
11102
+ if (listEls) {
11103
+ return this.tryToPushLiLevel(listEls, composer.selection);
11104
+ }
11105
+ return false;
11106
+ },
11107
+
11108
+ state: function(composer, command) {
11109
+ return false;
11110
+ },
11111
+
11112
+ tryToPushLiLevel: function(liNodes, selection) {
11113
+ var listTag, list, prevLi, liNode, prevLiList,
11114
+ found = false;
11115
+
11116
+ selection.executeAndRestoreRangy(function() {
11117
+
11118
+ for (var i = liNodes.length; i--;) {
11119
+ liNode = liNodes[i];
11120
+ listTag = (liNode.parentNode.nodeName === 'OL') ? 'OL' : 'UL';
11121
+ list = liNode.ownerDocument.createElement(listTag);
11122
+ prevLi = wysihtml5.dom.getPreviousElement(liNode);
11123
+ prevLiList = (prevLi) ? prevLi.querySelector('ul, ol') : null;
11124
+
11125
+ if (prevLi) {
11126
+ if (prevLiList) {
11127
+ prevLiList.appendChild(liNode);
11128
+ } else {
11129
+ list.appendChild(liNode);
11130
+ prevLi.appendChild(list);
11131
+ }
11132
+ found = true;
11133
+ }
11134
+ }
11135
+
11136
+ });
11137
+ return found;
11138
+ }
11139
+ };
11140
+ ;wysihtml5.commands.outdentList = {
11141
+ exec: function(composer, command, value) {
11142
+ var listEls = composer.selection.getSelectionParentsByTag('LI');
11143
+ if (listEls) {
11144
+ return this.tryToPullLiLevel(listEls, composer);
11145
+ }
11146
+ return false;
11147
+ },
11148
+
11149
+ state: function(composer, command) {
11150
+ return false;
11151
+ },
11152
+
11153
+ tryToPullLiLevel: function(liNodes, composer) {
11154
+ var listNode, outerListNode, outerLiNode, list, prevLi, liNode, afterList,
11155
+ found = false,
11156
+ that = this;
11157
+
11158
+ composer.selection.executeAndRestoreRangy(function() {
11159
+
11160
+ for (var i = liNodes.length; i--;) {
11161
+ liNode = liNodes[i];
11162
+ if (liNode.parentNode) {
11163
+ listNode = liNode.parentNode;
11164
+
11165
+ if (listNode.tagName === 'OL' || listNode.tagName === 'UL') {
11166
+ found = true;
11167
+
11168
+ outerListNode = wysihtml5.dom.getParentElement(listNode.parentNode, { nodeName: ['OL', 'UL']}, false, composer.element);
11169
+ outerLiNode = wysihtml5.dom.getParentElement(listNode.parentNode, { nodeName: ['LI']}, false, composer.element);
11170
+
11171
+ if (outerListNode && outerLiNode) {
11172
+
11173
+ if (liNode.nextSibling) {
11174
+ afterList = that.getAfterList(listNode, liNode);
11175
+ liNode.appendChild(afterList);
11176
+ }
11177
+ outerListNode.insertBefore(liNode, outerLiNode.nextSibling);
11178
+
11179
+ } else {
11180
+
11181
+ if (liNode.nextSibling) {
11182
+ afterList = that.getAfterList(listNode, liNode);
11183
+ liNode.appendChild(afterList);
11184
+ }
11185
+
11186
+ for (var j = liNode.childNodes.length; j--;) {
11187
+ listNode.parentNode.insertBefore(liNode.childNodes[j], listNode.nextSibling);
11188
+ }
11189
+
11190
+ listNode.parentNode.insertBefore(document.createElement('br'), listNode.nextSibling);
11191
+ liNode.parentNode.removeChild(liNode);
11192
+
11193
+ }
11194
+
11195
+ // cleanup
11196
+ if (listNode.childNodes.length === 0) {
11197
+ listNode.parentNode.removeChild(listNode);
11198
+ }
11199
+ }
11200
+ }
11201
+ }
11202
+
11203
+ });
11204
+ return found;
11205
+ },
11206
+
11207
+ getAfterList: function(listNode, liNode) {
11208
+ var nodeName = listNode.nodeName,
11209
+ newList = document.createElement(nodeName);
11210
+
11211
+ while (liNode.nextSibling) {
11212
+ newList.appendChild(liNode.nextSibling);
11213
+ }
11214
+ return newList;
11215
+ }
11216
+
11217
+ };;/**
11086
11218
  * Undo Manager for wysihtml5
11087
11219
  * slightly inspired by http://rniwa.com/editing/undomanager.html#the-undomanager-interface
11088
11220
  */
@@ -12059,9 +12191,12 @@ wysihtml5.views.View = Base.extend(
12059
12191
  }
12060
12192
  };
12061
12193
 
12062
- var handleDeleteKeyPress = function(event, selection, element) {
12194
+ var handleDeleteKeyPress = function(event, selection, element, composer) {
12063
12195
  if (selection.isCollapsed()) {
12064
- if (selection.caretIsInTheBeginnig()) {
12196
+ if (selection.caretIsInTheBeginnig('LI')) {
12197
+ event.preventDefault();
12198
+ composer.commands.exec('outdentList');
12199
+ } else if (selection.caretIsInTheBeginnig()) {
12065
12200
  event.preventDefault();
12066
12201
  } else {
12067
12202
  var beforeUneditable = selection.caretIsBeforeUneditable();
@@ -12078,38 +12213,11 @@ wysihtml5.views.View = Base.extend(
12078
12213
  }
12079
12214
  };
12080
12215
 
12081
- var tryToPushLiLevel = function(selection) {
12082
- var prevLi;
12083
- selection.executeAndRestoreRangy(function() {
12084
- var selNode = selection.getSelectedNode(),
12085
- liNode = (selNode.nodeName && selNode.nodeName === 'LI') ? selNode : selNode.parentNode,
12086
- listTag, list;
12087
-
12088
- if (liNode.getAttribute('class') === "rangySelectionBoundary") {
12089
- liNode = liNode.parentNode;
12090
- }
12091
-
12092
- if (liNode.nodeName === 'LI') {
12093
- listTag = (liNode.parentNode.nodeName === 'OL') ? 'OL' : 'UL';
12094
- list = selNode.ownerDocument.createElement(listTag);
12095
- prevLi = wysihtml5.dom.getPreviousElement(liNode);
12096
-
12097
- if (prevLi) {
12098
- list.appendChild(liNode);
12099
- prevLi.appendChild(list);
12100
- }
12101
- }
12102
-
12103
- });
12104
- return (prevLi) ? true : false;
12105
- };
12106
-
12107
-
12108
12216
  var handleTabKeyDown = function(composer, element) {
12109
12217
  if (!composer.selection.isCollapsed()) {
12110
12218
  composer.selection.deleteContents();
12111
12219
  } else if (composer.selection.caretIsInTheBeginnig('LI')) {
12112
- if (tryToPushLiLevel(composer.selection)) return;
12220
+ if (composer.commands.exec('indentList')) return;
12113
12221
  }
12114
12222
 
12115
12223
  // Is &emsp; close enough to tab. Could not find enough counter arguments for now.
@@ -12260,8 +12368,8 @@ wysihtml5.views.View = Base.extend(
12260
12368
  }
12261
12369
  if (keyCode === 8) {
12262
12370
  // delete key
12263
- handleDeleteKeyPress(event, that.selection, element);
12264
- } else if (keyCode === 9) {
12371
+ handleDeleteKeyPress(event, that.selection, element, that);
12372
+ } else if (that.config.handleTabKey && keyCode === 9) {
12265
12373
  event.preventDefault();
12266
12374
  handleTabKeyDown(that, element);
12267
12375
  }
@@ -12540,6 +12648,8 @@ wysihtml5.views.View = Base.extend(
12540
12648
  autoLink: true,
12541
12649
  // Includes table editing events and cell selection tracking
12542
12650
  handleTables: true,
12651
+ // Tab key inserts tab into text as default behaviour. It can be disabled to regain keyboard navigation
12652
+ handleTabKey: true,
12543
12653
  // Object which includes parser rules to apply when html gets inserted via copy & paste
12544
12654
  // See parser_rules/*.js for examples
12545
12655
  parserRules: { tags: { br: {}, span: {}, div: {}, p: {} }, classes: {} },
@@ -12561,7 +12671,6 @@ wysihtml5.views.View = Base.extend(
12561
12671
  cleanUp: true,
12562
12672
  // Whether to use div instead of secure iframe
12563
12673
  contentEditableMode: false,
12564
- xingAlert: false,
12565
12674
  // Classname of container that editor should not touch and pass through
12566
12675
  // Pass false to disable
12567
12676
  uneditableContainerClassname: "wysihtml5-uneditable-container"
@@ -12601,11 +12710,6 @@ wysihtml5.views.View = Base.extend(
12601
12710
  }
12602
12711
 
12603
12712
  this.on("beforeload", this.handleBeforeLoad);
12604
-
12605
-
12606
- if (this.config.xingAlert) {
12607
- try { console.log("Heya! This page is using wysihtml5 for rich text editing. Check out https://github.com/xing/wysihtml5");} catch(e) {}
12608
- }
12609
12713
  },
12610
12714
 
12611
12715
  handleBeforeLoad: function() {
@@ -25,7 +25,7 @@ if(!Array.isArray) {
25
25
  return Object.prototype.toString.call(arg) === '[object Array]';
26
26
  };
27
27
  };/**
28
- * @license wysihtml5x v0.4.5
28
+ * @license wysihtml5x v0.4.6
29
29
  * https://github.com/Edicy/wysihtml5
30
30
  *
31
31
  * Author: Christopher Blum (https://github.com/tiff)
@@ -36,7 +36,7 @@ if(!Array.isArray) {
36
36
  *
37
37
  */
38
38
  var wysihtml5 = {
39
- version: "0.4.5",
39
+ version: "0.4.6",
40
40
 
41
41
  // namespaces
42
42
  commands: {},
@@ -5362,74 +5362,22 @@ wysihtml5.dom.getParentElement = (function() {
5362
5362
  return styles[styles.length - 1] === cssStyle;
5363
5363
  }
5364
5364
 
5365
- function _getParentElementWithNodeName(node, nodeName, levels) {
5366
- while (levels-- && node && node.nodeName !== "BODY") {
5367
- if (_isSameNodeName(node.nodeName, nodeName)) {
5368
- return node;
5369
- }
5370
- node = node.parentNode;
5371
- }
5372
- return null;
5373
- }
5365
+ return function(node, matchingSet, levels, container) {
5366
+ var findByStyle = (matchingSet.cssStyle || matchingSet.styleRegExp),
5367
+ findByClass = (matchingSet.className || matchingSet.classRegExp);
5374
5368
 
5375
- function _getParentElementWithNodeNameAndClassName(node, nodeName, className, classRegExp, levels) {
5376
- while (levels-- && node && node.nodeName !== "BODY") {
5377
- if (_isElement(node) &&
5378
- _isSameNodeName(node.nodeName, nodeName) &&
5379
- _hasClassName(node, className, classRegExp)) {
5380
- return node;
5381
- }
5382
- node = node.parentNode;
5383
- }
5384
- return null;
5385
- }
5386
-
5387
- function _getParentElementWithNodeNameAndStyle(node, nodeName, cssStyle, styleRegExp, levels) {
5388
- while (levels-- && node && node.nodeName !== "BODY") {
5389
- if (_isElement(node) &&
5390
- _isSameNodeName(node.nodeName, nodeName) &&
5391
- _hasStyle(node, cssStyle, styleRegExp)
5392
- ) {
5393
- return node;
5394
- }
5395
- node = node.parentNode;
5396
- }
5397
- return null;
5398
- }
5369
+ levels = levels || 50; // Go max 50 nodes upwards from current node
5399
5370
 
5400
- function _getParentElementWithNodeNameAndClassNameAndStyle(node, nodeName, className, classRegExp, cssStyle, styleRegExp, levels) {
5401
- while (levels-- && node && node.nodeName !== "BODY") {
5402
- if (_isElement(node) &&
5403
- _isSameNodeName(node.nodeName, nodeName) &&
5404
- _hasStyle(node, cssStyle, styleRegExp) &&
5405
- _hasClassName(node, className, classRegExp)
5371
+ while (levels-- && node && node.nodeName !== "BODY" && (!container || node !== container)) {
5372
+ if (_isElement(node) && _isSameNodeName(node.nodeName, matchingSet.nodeName) &&
5373
+ (!findByStyle || _hasStyle(node, matchingSet.cssStyle, matchingSet.styleRegExp)) &&
5374
+ (!findByClass || _hasClassName(node, matchingSet.className, matchingSet.classRegExp))
5406
5375
  ) {
5407
5376
  return node;
5408
5377
  }
5409
5378
  node = node.parentNode;
5410
5379
  }
5411
5380
  return null;
5412
- }
5413
-
5414
- return function(node, matchingSet, levels) {
5415
- levels = levels || 50; // Go max 50 nodes upwards from current node
5416
- if ((matchingSet.className || matchingSet.classRegExp) && (matchingSet.cssStyle || matchingSet.styleRegExp)) {
5417
- return _getParentElementWithNodeNameAndClassNameAndStyle(
5418
- node, matchingSet.nodeName, matchingSet.className, matchingSet.classRegExp, matchingSet.cssStyle, matchingSet.styleRegExp, levels
5419
- );
5420
- } else if (matchingSet.className || matchingSet.classRegExp) {
5421
- return _getParentElementWithNodeNameAndClassName(
5422
- node, matchingSet.nodeName, matchingSet.className, matchingSet.classRegExp, levels
5423
- );
5424
- } else if (matchingSet.cssStyle || matchingSet.styleRegExp) {
5425
- return _getParentElementWithNodeNameAndStyle(
5426
- node, matchingSet.nodeName, matchingSet.cssStyle, matchingSet.styleRegExp, levels
5427
- );
5428
- } else {
5429
- return _getParentElementWithNodeName(
5430
- node, matchingSet.nodeName, levels
5431
- );
5432
- }
5433
5381
  };
5434
5382
  })();
5435
5383
  ;wysihtml5.dom.getNextElement = function(node){
@@ -5885,7 +5833,6 @@ wysihtml5.dom.parse = (function() {
5885
5833
  nodeName = oldNode.nodeName.toLowerCase(),
5886
5834
  scopeName = oldNode.scopeName;
5887
5835
 
5888
-
5889
5836
  /**
5890
5837
  * We already parsed that element
5891
5838
  * ignore it! (yes, this sometimes happens in IE8 when the html is invalid)
@@ -5940,7 +5887,7 @@ wysihtml5.dom.parse = (function() {
5940
5887
  _handleAttributes(oldNode, newNode, rule);
5941
5888
  _handleStyles(oldNode, newNode, rule);
5942
5889
  // tests if type condition is met or node should be removed/unwrapped
5943
- if (rule.one_of_type && !_testTypes(newNode, currentRules, rule.one_of_type)) {
5890
+ if (rule.one_of_type && !_testTypes(oldNode, currentRules, rule.one_of_type)) {
5944
5891
  return (rule.remove_action && rule.remove_action == "unwrap") ? false : null;
5945
5892
  }
5946
5893
 
@@ -5985,6 +5932,18 @@ wysihtml5.dom.parse = (function() {
5985
5932
  nodeStyles = oldNode.getAttribute("style"),
5986
5933
  classesLength, s, s_corrected, a, attr, currentClass, styleProp;
5987
5934
 
5935
+ // test for methods
5936
+ if (definition.methods) {
5937
+ for (var m in definition.methods) {
5938
+ if (definition.methods.hasOwnProperty(m) && typeCeckMethods[m]) {
5939
+
5940
+ if (typeCeckMethods[m](oldNode)) {
5941
+ return true;
5942
+ }
5943
+ }
5944
+ }
5945
+ }
5946
+
5988
5947
  // test for classes, if one found return true
5989
5948
  if (nodeClasses && definition.classes) {
5990
5949
  nodeClasses = nodeClasses.replace(/^\s+/g, '').replace(/\s+$/g, '').split(WHITE_SPACE_REG_EXP);
@@ -6364,6 +6323,40 @@ wysihtml5.dom.parse = (function() {
6364
6323
  })()
6365
6324
  };
6366
6325
 
6326
+ // checks if element is possibly visible
6327
+ var typeCeckMethods = {
6328
+ has_visible_contet: (function() {
6329
+ var txt,
6330
+ isVisible = false,
6331
+ visibleElements = ['img', 'video', 'picture', 'br', 'script', 'noscript',
6332
+ 'style', 'table', 'iframe', 'object', 'embed', 'audio',
6333
+ 'svg', 'input', 'button', 'select','textarea', 'canvas'];
6334
+
6335
+ return function(el) {
6336
+
6337
+ // has visible innertext. so is visible
6338
+ txt = (el.innerText || el.textContent).replace(/\s/g, '');
6339
+ if (txt && txt.length > 0) {
6340
+ return true;
6341
+ }
6342
+
6343
+ // matches list of visible dimensioned elements
6344
+ for (var i = visibleElements.length; i--;) {
6345
+ if (el.querySelector(visibleElements[i])) {
6346
+ return true;
6347
+ }
6348
+ }
6349
+
6350
+ // try to measure dimesions in last resort. (can find only of elements in dom)
6351
+ if (el.offsetWidth && el.offsetWidth > 0 && el.offsetHeight && el.offsetHeight > 0) {
6352
+ return true;
6353
+ }
6354
+
6355
+ return false;
6356
+ };
6357
+ })()
6358
+ };
6359
+
6367
6360
  return parse;
6368
6361
  })();
6369
6362
  ;/**
@@ -8555,6 +8548,19 @@ wysihtml5.quirks.ensureProperClearing = (function() {
8555
8548
  return (ret !== this.contain) ? ret : false;
8556
8549
  },
8557
8550
 
8551
+ getSelectionParentsByTag: function(tagName) {
8552
+ var nodes = this.getSelectedOwnNodes(),
8553
+ curEl, parents = [];
8554
+
8555
+ for (var i = 0, maxi = nodes.length; i < maxi; i++) {
8556
+ curEl = (nodes[i].nodeName && nodes[i].nodeName === 'LI') ? nodes[i] : wysihtml5.dom.getParentElement(nodes[i], { nodeName: ['LI']}, false, this.contain);
8557
+ if (curEl) {
8558
+ parents.push(curEl);
8559
+ }
8560
+ }
8561
+ return (parents.length) ? parents : null;
8562
+ },
8563
+
8558
8564
  getRangeToNodeEnd: function() {
8559
8565
  if (this.isCollapsed()) {
8560
8566
  var range = this.getRange(),
@@ -9606,6 +9612,7 @@ wysihtml5.quirks.ensureProperClearing = (function() {
9606
9612
  ancestor, styleAncestor, textNodes;
9607
9613
 
9608
9614
  for (var ri = range.length; ri--;) {
9615
+
9609
9616
  textNodes = range[ri].getNodes([wysihtml5.TEXT_NODE]);
9610
9617
  if (!textNodes.length) {
9611
9618
  ancestor = this.getAncestorWithClass(range[ri].startContainer);
@@ -9621,10 +9628,11 @@ wysihtml5.quirks.ensureProperClearing = (function() {
9621
9628
  if (!ancestor) {
9622
9629
  ancestor = this.getAncestorWithStyle(textNodes[i]);
9623
9630
  }
9624
- if (!(selectedText != "" && !ancestor)) {
9631
+ if (ancestor && selectedText != "") {
9625
9632
  ancestors.push(ancestor);
9626
9633
  }
9627
9634
  }
9635
+
9628
9636
  }
9629
9637
 
9630
9638
  return (ancestors.length) ? ancestors : false;
@@ -10461,13 +10469,19 @@ wysihtml5.commands.formatCode = {
10461
10469
  }
10462
10470
 
10463
10471
  function _getApplier(tagName, className, classRegExp, cssStyle, styleRegExp, container) {
10464
- var identifier = tagName + ":" + className;
10472
+ var identifier = tagName;
10473
+
10474
+ if (className) {
10475
+ identifier += ":" + className;
10476
+ }
10465
10477
  if (cssStyle) {
10466
10478
  identifier += ":" + cssStyle;
10467
10479
  }
10480
+
10468
10481
  if (!htmlApplier[identifier]) {
10469
10482
  htmlApplier[identifier] = new wysihtml5.selection.HTMLApplier(_getTagNames(tagName), className, classRegExp, true, cssStyle, styleRegExp, container);
10470
10483
  }
10484
+
10471
10485
  return htmlApplier[identifier];
10472
10486
  }
10473
10487
 
@@ -10546,7 +10560,7 @@ wysihtml5.commands.formatCode = {
10546
10560
 
10547
10561
  ownRanges = composer.selection.getOwnRanges();
10548
10562
 
10549
- if (ownRanges.length == 0) {
10563
+ if (!ownRanges || ownRanges.length === 0) {
10550
10564
  return false;
10551
10565
  }
10552
10566
 
@@ -11082,7 +11096,125 @@ wysihtml5.commands.formatCode = {
11082
11096
  return false;
11083
11097
  }
11084
11098
  };
11085
- ;/**
11099
+ ;wysihtml5.commands.indentList = {
11100
+ exec: function(composer, command, value) {
11101
+ var listEls = composer.selection.getSelectionParentsByTag('LI');
11102
+ if (listEls) {
11103
+ return this.tryToPushLiLevel(listEls, composer.selection);
11104
+ }
11105
+ return false;
11106
+ },
11107
+
11108
+ state: function(composer, command) {
11109
+ return false;
11110
+ },
11111
+
11112
+ tryToPushLiLevel: function(liNodes, selection) {
11113
+ var listTag, list, prevLi, liNode, prevLiList,
11114
+ found = false;
11115
+
11116
+ selection.executeAndRestoreRangy(function() {
11117
+
11118
+ for (var i = liNodes.length; i--;) {
11119
+ liNode = liNodes[i];
11120
+ listTag = (liNode.parentNode.nodeName === 'OL') ? 'OL' : 'UL';
11121
+ list = liNode.ownerDocument.createElement(listTag);
11122
+ prevLi = wysihtml5.dom.getPreviousElement(liNode);
11123
+ prevLiList = (prevLi) ? prevLi.querySelector('ul, ol') : null;
11124
+
11125
+ if (prevLi) {
11126
+ if (prevLiList) {
11127
+ prevLiList.appendChild(liNode);
11128
+ } else {
11129
+ list.appendChild(liNode);
11130
+ prevLi.appendChild(list);
11131
+ }
11132
+ found = true;
11133
+ }
11134
+ }
11135
+
11136
+ });
11137
+ return found;
11138
+ }
11139
+ };
11140
+ ;wysihtml5.commands.outdentList = {
11141
+ exec: function(composer, command, value) {
11142
+ var listEls = composer.selection.getSelectionParentsByTag('LI');
11143
+ if (listEls) {
11144
+ return this.tryToPullLiLevel(listEls, composer);
11145
+ }
11146
+ return false;
11147
+ },
11148
+
11149
+ state: function(composer, command) {
11150
+ return false;
11151
+ },
11152
+
11153
+ tryToPullLiLevel: function(liNodes, composer) {
11154
+ var listNode, outerListNode, outerLiNode, list, prevLi, liNode, afterList,
11155
+ found = false,
11156
+ that = this;
11157
+
11158
+ composer.selection.executeAndRestoreRangy(function() {
11159
+
11160
+ for (var i = liNodes.length; i--;) {
11161
+ liNode = liNodes[i];
11162
+ if (liNode.parentNode) {
11163
+ listNode = liNode.parentNode;
11164
+
11165
+ if (listNode.tagName === 'OL' || listNode.tagName === 'UL') {
11166
+ found = true;
11167
+
11168
+ outerListNode = wysihtml5.dom.getParentElement(listNode.parentNode, { nodeName: ['OL', 'UL']}, false, composer.element);
11169
+ outerLiNode = wysihtml5.dom.getParentElement(listNode.parentNode, { nodeName: ['LI']}, false, composer.element);
11170
+
11171
+ if (outerListNode && outerLiNode) {
11172
+
11173
+ if (liNode.nextSibling) {
11174
+ afterList = that.getAfterList(listNode, liNode);
11175
+ liNode.appendChild(afterList);
11176
+ }
11177
+ outerListNode.insertBefore(liNode, outerLiNode.nextSibling);
11178
+
11179
+ } else {
11180
+
11181
+ if (liNode.nextSibling) {
11182
+ afterList = that.getAfterList(listNode, liNode);
11183
+ liNode.appendChild(afterList);
11184
+ }
11185
+
11186
+ for (var j = liNode.childNodes.length; j--;) {
11187
+ listNode.parentNode.insertBefore(liNode.childNodes[j], listNode.nextSibling);
11188
+ }
11189
+
11190
+ listNode.parentNode.insertBefore(document.createElement('br'), listNode.nextSibling);
11191
+ liNode.parentNode.removeChild(liNode);
11192
+
11193
+ }
11194
+
11195
+ // cleanup
11196
+ if (listNode.childNodes.length === 0) {
11197
+ listNode.parentNode.removeChild(listNode);
11198
+ }
11199
+ }
11200
+ }
11201
+ }
11202
+
11203
+ });
11204
+ return found;
11205
+ },
11206
+
11207
+ getAfterList: function(listNode, liNode) {
11208
+ var nodeName = listNode.nodeName,
11209
+ newList = document.createElement(nodeName);
11210
+
11211
+ while (liNode.nextSibling) {
11212
+ newList.appendChild(liNode.nextSibling);
11213
+ }
11214
+ return newList;
11215
+ }
11216
+
11217
+ };;/**
11086
11218
  * Undo Manager for wysihtml5
11087
11219
  * slightly inspired by http://rniwa.com/editing/undomanager.html#the-undomanager-interface
11088
11220
  */
@@ -12059,9 +12191,12 @@ wysihtml5.views.View = Base.extend(
12059
12191
  }
12060
12192
  };
12061
12193
 
12062
- var handleDeleteKeyPress = function(event, selection, element) {
12194
+ var handleDeleteKeyPress = function(event, selection, element, composer) {
12063
12195
  if (selection.isCollapsed()) {
12064
- if (selection.caretIsInTheBeginnig()) {
12196
+ if (selection.caretIsInTheBeginnig('LI')) {
12197
+ event.preventDefault();
12198
+ composer.commands.exec('outdentList');
12199
+ } else if (selection.caretIsInTheBeginnig()) {
12065
12200
  event.preventDefault();
12066
12201
  } else {
12067
12202
  var beforeUneditable = selection.caretIsBeforeUneditable();
@@ -12078,38 +12213,11 @@ wysihtml5.views.View = Base.extend(
12078
12213
  }
12079
12214
  };
12080
12215
 
12081
- var tryToPushLiLevel = function(selection) {
12082
- var prevLi;
12083
- selection.executeAndRestoreRangy(function() {
12084
- var selNode = selection.getSelectedNode(),
12085
- liNode = (selNode.nodeName && selNode.nodeName === 'LI') ? selNode : selNode.parentNode,
12086
- listTag, list;
12087
-
12088
- if (liNode.getAttribute('class') === "rangySelectionBoundary") {
12089
- liNode = liNode.parentNode;
12090
- }
12091
-
12092
- if (liNode.nodeName === 'LI') {
12093
- listTag = (liNode.parentNode.nodeName === 'OL') ? 'OL' : 'UL';
12094
- list = selNode.ownerDocument.createElement(listTag);
12095
- prevLi = wysihtml5.dom.getPreviousElement(liNode);
12096
-
12097
- if (prevLi) {
12098
- list.appendChild(liNode);
12099
- prevLi.appendChild(list);
12100
- }
12101
- }
12102
-
12103
- });
12104
- return (prevLi) ? true : false;
12105
- };
12106
-
12107
-
12108
12216
  var handleTabKeyDown = function(composer, element) {
12109
12217
  if (!composer.selection.isCollapsed()) {
12110
12218
  composer.selection.deleteContents();
12111
12219
  } else if (composer.selection.caretIsInTheBeginnig('LI')) {
12112
- if (tryToPushLiLevel(composer.selection)) return;
12220
+ if (composer.commands.exec('indentList')) return;
12113
12221
  }
12114
12222
 
12115
12223
  // Is &emsp; close enough to tab. Could not find enough counter arguments for now.
@@ -12260,8 +12368,8 @@ wysihtml5.views.View = Base.extend(
12260
12368
  }
12261
12369
  if (keyCode === 8) {
12262
12370
  // delete key
12263
- handleDeleteKeyPress(event, that.selection, element);
12264
- } else if (keyCode === 9) {
12371
+ handleDeleteKeyPress(event, that.selection, element, that);
12372
+ } else if (that.config.handleTabKey && keyCode === 9) {
12265
12373
  event.preventDefault();
12266
12374
  handleTabKeyDown(that, element);
12267
12375
  }
@@ -12540,6 +12648,8 @@ wysihtml5.views.View = Base.extend(
12540
12648
  autoLink: true,
12541
12649
  // Includes table editing events and cell selection tracking
12542
12650
  handleTables: true,
12651
+ // Tab key inserts tab into text as default behaviour. It can be disabled to regain keyboard navigation
12652
+ handleTabKey: true,
12543
12653
  // Object which includes parser rules to apply when html gets inserted via copy & paste
12544
12654
  // See parser_rules/*.js for examples
12545
12655
  parserRules: { tags: { br: {}, span: {}, div: {}, p: {} }, classes: {} },
@@ -12561,7 +12671,6 @@ wysihtml5.views.View = Base.extend(
12561
12671
  cleanUp: true,
12562
12672
  // Whether to use div instead of secure iframe
12563
12673
  contentEditableMode: false,
12564
- xingAlert: false,
12565
12674
  // Classname of container that editor should not touch and pass through
12566
12675
  // Pass false to disable
12567
12676
  uneditableContainerClassname: "wysihtml5-uneditable-container"
@@ -12601,11 +12710,6 @@ wysihtml5.views.View = Base.extend(
12601
12710
  }
12602
12711
 
12603
12712
  this.on("beforeload", this.handleBeforeLoad);
12604
-
12605
-
12606
- if (this.config.xingAlert) {
12607
- try { console.log("Heya! This page is using wysihtml5 for rich text editing. Check out https://github.com/xing/wysihtml5");} catch(e) {}
12608
- }
12609
12713
  },
12610
12714
 
12611
12715
  handleBeforeLoad: function() {
metadata CHANGED
@@ -1,72 +1,65 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: wysihtml5x-rails
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 4
8
- - 5
9
- version: 0.4.5
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.6
10
5
  platform: ruby
11
- authors:
6
+ authors:
12
7
  - Tanel Jakobsoo
13
8
  autorequire:
14
9
  bindir: bin
15
10
  cert_chain: []
16
-
17
- date: 2014-05-06 00:00:00 +03:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
11
+ date: 2014-06-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
21
14
  name: railties
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- requirements:
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
25
17
  - - ">="
26
- - !ruby/object:Gem::Version
27
- segments:
28
- - 3
29
- - 1
30
- - 0
18
+ - !ruby/object:Gem::Version
31
19
  version: 3.1.0
32
20
  type: :runtime
33
- version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
35
- name: bundler
36
21
  prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
38
- requirements:
39
- - - ~>
40
- - !ruby/object:Gem::Version
41
- segments:
42
- - 1
43
- - 3
44
- version: "1.3"
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 3.1.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
45
34
  type: :development
46
- version_requirements: *id002
47
- - !ruby/object:Gem::Dependency
48
- name: rake
49
35
  prerelease: false
50
- requirement: &id003 !ruby/object:Gem::Requirement
51
- requirements:
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
52
45
  - - ">="
53
- - !ruby/object:Gem::Version
54
- segments:
55
- - 0
56
- version: "0"
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
57
48
  type: :development
58
- version_requirements: *id003
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
59
55
  description: A wysiwyg5x text editor for Rails assets pipeline
60
- email:
56
+ email:
61
57
  - tanel@fraktal.ee
62
58
  executables: []
63
-
64
59
  extensions: []
65
-
66
60
  extra_rdoc_files: []
67
-
68
- files:
69
- - .gitignore
61
+ files:
62
+ - ".gitignore"
70
63
  - Gemfile
71
64
  - LICENSE.txt
72
65
  - README.md
@@ -80,35 +73,29 @@ files:
80
73
  - vendor/assets/javascripts/wysihtml5x.js
81
74
  - vendor/assets/stylesheets/wysihtml5x.css
82
75
  - wysihtml5x-rails.gemspec
83
- has_rdoc: true
84
76
  homepage: https://github.com/Edicy/wysihtml5x-rails
85
- licenses:
77
+ licenses:
86
78
  - MIT
79
+ metadata: {}
87
80
  post_install_message:
88
81
  rdoc_options: []
89
-
90
- require_paths:
82
+ require_paths:
91
83
  - lib
92
- required_ruby_version: !ruby/object:Gem::Requirement
93
- requirements:
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
94
86
  - - ">="
95
- - !ruby/object:Gem::Version
96
- segments:
97
- - 0
98
- version: "0"
99
- required_rubygems_version: !ruby/object:Gem::Requirement
100
- requirements:
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
101
91
  - - ">="
102
- - !ruby/object:Gem::Version
103
- segments:
104
- - 0
105
- version: "0"
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
106
94
  requirements: []
107
-
108
95
  rubyforge_project:
109
- rubygems_version: 1.3.6
96
+ rubygems_version: 2.2.2
110
97
  signing_key:
111
- specification_version: 3
112
- summary: Wysihtml5x (http://edicy.github.io/wysihtml5) text editor for Rails assets pipeline.
98
+ specification_version: 4
99
+ summary: Wysihtml5x (http://edicy.github.io/wysihtml5) text editor for Rails assets
100
+ pipeline.
113
101
  test_files: []
114
-