Skip to content

Commit

Permalink
fix(taBind): Fix paste issues
Browse files Browse the repository at this point in the history
Fixes #407
Ref #392 Partial fix
  • Loading branch information
SimeonC authored and SimeonC committed Nov 27, 2014
1 parent 75cc144 commit f9d7e42
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 7 deletions.
2 changes: 1 addition & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ module.exports = function (grunt) {
}
},
jshint: {
files: ['src/textAngular.js', 'src/textAngularSetup.js', 'test/*.spec.js', 'test/taBind/*.spec.js'],// don't hint the textAngularSanitize as they will fail
files: ['lib/*.js', 'src/textAngular.js', 'src/textAngularSetup.js', 'test/*.spec.js', 'test/taBind/*.spec.js'],// don't hint the textAngularSanitize as they will fail
options: {
eqeqeq: true,
immed: true,
Expand Down
4 changes: 2 additions & 2 deletions dist/textAngular.min.js

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions lib/DOM.js
Original file line number Diff line number Diff line change
Expand Up @@ -323,11 +323,13 @@ function($window, $document){
}
}
for(var _n = 0; _n < nodes.length; _n++) lastNode = frag.appendChild(nodes[_n]);
if(!isInline && range.collapsed && /^(|<br(|\/)>)$/i.test(range.startContainer.innerHTML)) range.selectNode(range.startContainer);
}else{
isInline = true;
// paste text of some sort
lastNode = frag = _document.createTextNode(html);
}

// Other Edge case - selected data spans multiple blocks.
if(isInline){
range.deleteContents();
Expand Down
24 changes: 24 additions & 0 deletions lib/taBind.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ angular.module('textAngular.taBind', ['textAngular.factories', 'textAngular.DOM'
$window.rangy.restoreSelection(_savedSelection);
/* istanbul ignore else: don't care if nothing pasted */
if(text.trim().length){
// test paste from word/microsoft product
if(text.match(/class=["']*Mso(Normal|List)/i)){
var textFragment = text.match(/<!--StartFragment-->([\s\S]*?)<!--EndFragment-->/i);
if(!textFragment) textFragment = text;
Expand Down Expand Up @@ -265,6 +266,29 @@ angular.module('textAngular.taBind', ['textAngular.factories', 'textAngular.DOM'
});
angular.forEach(targetDom.find('font'), _unwrapElement);
text = targetDom.html();
}else{
// remove unnecessary chrome insert
text = text.replace(/<(|\/)meta[^>]*?>/ig, '');
if(text.match(/<[^>]*?(ta-bind)[^>]*?>/)){
// entire text-angular or ta-bind has been pasted, REMOVE AT ONCE!!
if(text.match(/<[^>]*?(text-angular)[^>]*?>/)){
var _el = angular.element("<div>" + text + "</div>");
_el.find('textarea').remove();
var binds = getByAttribute(_el, 'ta-bind');
for(var _b = 0; _b < binds.length; _b++){
var _target = binds[_b][0].parentNode.parentNode;
for(var _c = 0; _c < binds[_b][0].childNodes.length; _c++){
_target.parentNode.insertBefore(binds[_b][0].childNodes[_c], _target);
}
_target.parentNode.removeChild(_target);
}
text = _el.html().replace('<br class="Apple-interchange-newline">', '');
}
}else if(text.match(/^<span/)){
// in case of pasting only a span - chrome paste, remove them. THis is just some wierd formatting
text = text.replace(/<(|\/)span[^>]*?>/ig, '');
}
text = text.replace(/<br class="Apple-interchange-newline"[^>]*?>/ig, '');
}

text = taSanitize(text, '', _disableSanitizer);
Expand Down
26 changes: 26 additions & 0 deletions src/textAngular.js
Original file line number Diff line number Diff line change
Expand Up @@ -606,11 +606,13 @@ function($window, $document){
}
}
for(var _n = 0; _n < nodes.length; _n++) lastNode = frag.appendChild(nodes[_n]);
if(!isInline && range.collapsed && /^(|<br(|\/)>)$/i.test(range.startContainer.innerHTML)) range.selectNode(range.startContainer);
}else{
isInline = true;
// paste text of some sort
lastNode = frag = _document.createTextNode(html);
}

// Other Edge case - selected data spans multiple blocks.
if(isInline){
range.deleteContents();
Expand Down Expand Up @@ -907,6 +909,7 @@ angular.module('textAngular.taBind', ['textAngular.factories', 'textAngular.DOM'
$window.rangy.restoreSelection(_savedSelection);
/* istanbul ignore else: don't care if nothing pasted */
if(text.trim().length){
// test paste from word/microsoft product
if(text.match(/class=["']*Mso(Normal|List)/i)){
var textFragment = text.match(/<!--StartFragment-->([\s\S]*?)<!--EndFragment-->/i);
if(!textFragment) textFragment = text;
Expand Down Expand Up @@ -999,6 +1002,29 @@ angular.module('textAngular.taBind', ['textAngular.factories', 'textAngular.DOM'
});
angular.forEach(targetDom.find('font'), _unwrapElement);
text = targetDom.html();
}else{
// remove unnecessary chrome insert
text = text.replace(/<(|\/)meta[^>]*?>/ig, '');
if(text.match(/<[^>]*?(ta-bind)[^>]*?>/)){
// entire text-angular or ta-bind has been pasted, REMOVE AT ONCE!!
if(text.match(/<[^>]*?(text-angular)[^>]*?>/)){
var _el = angular.element("<div>" + text + "</div>");
_el.find('textarea').remove();
var binds = getByAttribute(_el, 'ta-bind');
for(var _b = 0; _b < binds.length; _b++){
var _target = binds[_b][0].parentNode.parentNode;
for(var _c = 0; _c < binds[_b][0].childNodes.length; _c++){
_target.parentNode.insertBefore(binds[_b][0].childNodes[_c], _target);
}
_target.parentNode.removeChild(_target);
}
text = _el.html().replace('<br class="Apple-interchange-newline">', '');
}
}else if(text.match(/^<span/)){
// in case of pasting only a span - chrome paste, remove them. THis is just some wierd formatting
text = text.replace(/<(|\/)span[^>]*?>/ig, '');
}
text = text.replace(/<br class="Apple-interchange-newline"[^>]*?>/ig, '');
}

text = taSanitize(text, '', _disableSanitizer);
Expand Down
8 changes: 4 additions & 4 deletions test/taBind/taBind.events.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,17 +144,17 @@ describe('taBind.events', function () {
// var text = (e.originalEvent || e).clipboardData.getData('text/plain') || $window.clipboardData.getData('Text');
describe('should update model from paste keeping all styles', function () {
it('non-ie based w/o jquery', inject(function($window){
element.triggerHandler('paste', {clipboardData: {types: ['text/html'], getData: function(){ return '<span style="font-size:10px">Test 4 Content</span>'; }}});
element.triggerHandler('paste', {clipboardData: {types: ['text/html'], getData: function(){ return '<font style="font-size:10px">Test 4 Content</font>'; }}});
$timeout.flush();
$rootScope.$digest();
expect($rootScope.html).toBe('<p><span style="font-size:10px">Test 4 Content</span></p>');
expect($rootScope.html).toBe('<p><font style="font-size:10px">Test 4 Content</font></p>');
}));

it('non-ie based w/ jquery', inject(function($window){
element.triggerHandler('paste', {originalEvent: {clipboardData: {types: ['text/html'], getData: function(){ return '<span style="font-size:10px">Test 4 Content</span>';} }}});
element.triggerHandler('paste', {originalEvent: {clipboardData: {types: ['text/html'], getData: function(){ return '<font style="font-size:10px">Test 4 Content</font>';} }}});
$timeout.flush();
$rootScope.$digest();
expect($rootScope.html).toBe('<p><span style="font-size:10px">Test 4 Content</span></p>');
expect($rootScope.html).toBe('<p><font style="font-size:10px">Test 4 Content</font></p>');
}));

});
Expand Down

0 comments on commit f9d7e42

Please sign in to comment.