Skip to content

Commit f9d7e42

Browse files
SimeonCSimeonC
SimeonC
authored and
SimeonC
committed
fix(taBind): Fix paste issues
Fixes #407 Ref #392 Partial fix
1 parent 75cc144 commit f9d7e42

File tree

6 files changed

+59
-7
lines changed

6 files changed

+59
-7
lines changed

Gruntfile.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ module.exports = function (grunt) {
5353
}
5454
},
5555
jshint: {
56-
files: ['src/textAngular.js', 'src/textAngularSetup.js', 'test/*.spec.js', 'test/taBind/*.spec.js'],// don't hint the textAngularSanitize as they will fail
56+
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
5757
options: {
5858
eqeqeq: true,
5959
immed: true,

dist/textAngular.min.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/DOM.js

+2
Original file line numberDiff line numberDiff line change
@@ -323,11 +323,13 @@ function($window, $document){
323323
}
324324
}
325325
for(var _n = 0; _n < nodes.length; _n++) lastNode = frag.appendChild(nodes[_n]);
326+
if(!isInline && range.collapsed && /^(|<br(|\/)>)$/i.test(range.startContainer.innerHTML)) range.selectNode(range.startContainer);
326327
}else{
327328
isInline = true;
328329
// paste text of some sort
329330
lastNode = frag = _document.createTextNode(html);
330331
}
332+
331333
// Other Edge case - selected data spans multiple blocks.
332334
if(isInline){
333335
range.deleteContents();

lib/taBind.js

+24
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ angular.module('textAngular.taBind', ['textAngular.factories', 'textAngular.DOM'
173173
$window.rangy.restoreSelection(_savedSelection);
174174
/* istanbul ignore else: don't care if nothing pasted */
175175
if(text.trim().length){
176+
// test paste from word/microsoft product
176177
if(text.match(/class=["']*Mso(Normal|List)/i)){
177178
var textFragment = text.match(/<!--StartFragment-->([\s\S]*?)<!--EndFragment-->/i);
178179
if(!textFragment) textFragment = text;
@@ -265,6 +266,29 @@ angular.module('textAngular.taBind', ['textAngular.factories', 'textAngular.DOM'
265266
});
266267
angular.forEach(targetDom.find('font'), _unwrapElement);
267268
text = targetDom.html();
269+
}else{
270+
// remove unnecessary chrome insert
271+
text = text.replace(/<(|\/)meta[^>]*?>/ig, '');
272+
if(text.match(/<[^>]*?(ta-bind)[^>]*?>/)){
273+
// entire text-angular or ta-bind has been pasted, REMOVE AT ONCE!!
274+
if(text.match(/<[^>]*?(text-angular)[^>]*?>/)){
275+
var _el = angular.element("<div>" + text + "</div>");
276+
_el.find('textarea').remove();
277+
var binds = getByAttribute(_el, 'ta-bind');
278+
for(var _b = 0; _b < binds.length; _b++){
279+
var _target = binds[_b][0].parentNode.parentNode;
280+
for(var _c = 0; _c < binds[_b][0].childNodes.length; _c++){
281+
_target.parentNode.insertBefore(binds[_b][0].childNodes[_c], _target);
282+
}
283+
_target.parentNode.removeChild(_target);
284+
}
285+
text = _el.html().replace('<br class="Apple-interchange-newline">', '');
286+
}
287+
}else if(text.match(/^<span/)){
288+
// in case of pasting only a span - chrome paste, remove them. THis is just some wierd formatting
289+
text = text.replace(/<(|\/)span[^>]*?>/ig, '');
290+
}
291+
text = text.replace(/<br class="Apple-interchange-newline"[^>]*?>/ig, '');
268292
}
269293

270294
text = taSanitize(text, '', _disableSanitizer);

src/textAngular.js

+26
Original file line numberDiff line numberDiff line change
@@ -606,11 +606,13 @@ function($window, $document){
606606
}
607607
}
608608
for(var _n = 0; _n < nodes.length; _n++) lastNode = frag.appendChild(nodes[_n]);
609+
if(!isInline && range.collapsed && /^(|<br(|\/)>)$/i.test(range.startContainer.innerHTML)) range.selectNode(range.startContainer);
609610
}else{
610611
isInline = true;
611612
// paste text of some sort
612613
lastNode = frag = _document.createTextNode(html);
613614
}
615+
614616
// Other Edge case - selected data spans multiple blocks.
615617
if(isInline){
616618
range.deleteContents();
@@ -907,6 +909,7 @@ angular.module('textAngular.taBind', ['textAngular.factories', 'textAngular.DOM'
907909
$window.rangy.restoreSelection(_savedSelection);
908910
/* istanbul ignore else: don't care if nothing pasted */
909911
if(text.trim().length){
912+
// test paste from word/microsoft product
910913
if(text.match(/class=["']*Mso(Normal|List)/i)){
911914
var textFragment = text.match(/<!--StartFragment-->([\s\S]*?)<!--EndFragment-->/i);
912915
if(!textFragment) textFragment = text;
@@ -999,6 +1002,29 @@ angular.module('textAngular.taBind', ['textAngular.factories', 'textAngular.DOM'
9991002
});
10001003
angular.forEach(targetDom.find('font'), _unwrapElement);
10011004
text = targetDom.html();
1005+
}else{
1006+
// remove unnecessary chrome insert
1007+
text = text.replace(/<(|\/)meta[^>]*?>/ig, '');
1008+
if(text.match(/<[^>]*?(ta-bind)[^>]*?>/)){
1009+
// entire text-angular or ta-bind has been pasted, REMOVE AT ONCE!!
1010+
if(text.match(/<[^>]*?(text-angular)[^>]*?>/)){
1011+
var _el = angular.element("<div>" + text + "</div>");
1012+
_el.find('textarea').remove();
1013+
var binds = getByAttribute(_el, 'ta-bind');
1014+
for(var _b = 0; _b < binds.length; _b++){
1015+
var _target = binds[_b][0].parentNode.parentNode;
1016+
for(var _c = 0; _c < binds[_b][0].childNodes.length; _c++){
1017+
_target.parentNode.insertBefore(binds[_b][0].childNodes[_c], _target);
1018+
}
1019+
_target.parentNode.removeChild(_target);
1020+
}
1021+
text = _el.html().replace('<br class="Apple-interchange-newline">', '');
1022+
}
1023+
}else if(text.match(/^<span/)){
1024+
// in case of pasting only a span - chrome paste, remove them. THis is just some wierd formatting
1025+
text = text.replace(/<(|\/)span[^>]*?>/ig, '');
1026+
}
1027+
text = text.replace(/<br class="Apple-interchange-newline"[^>]*?>/ig, '');
10021028
}
10031029

10041030
text = taSanitize(text, '', _disableSanitizer);

test/taBind/taBind.events.spec.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -144,17 +144,17 @@ describe('taBind.events', function () {
144144
// var text = (e.originalEvent || e).clipboardData.getData('text/plain') || $window.clipboardData.getData('Text');
145145
describe('should update model from paste keeping all styles', function () {
146146
it('non-ie based w/o jquery', inject(function($window){
147-
element.triggerHandler('paste', {clipboardData: {types: ['text/html'], getData: function(){ return '<span style="font-size:10px">Test 4 Content</span>'; }}});
147+
element.triggerHandler('paste', {clipboardData: {types: ['text/html'], getData: function(){ return '<font style="font-size:10px">Test 4 Content</font>'; }}});
148148
$timeout.flush();
149149
$rootScope.$digest();
150-
expect($rootScope.html).toBe('<p><span style="font-size:10px">Test 4 Content</span></p>');
150+
expect($rootScope.html).toBe('<p><font style="font-size:10px">Test 4 Content</font></p>');
151151
}));
152152

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

160160
});

0 commit comments

Comments
 (0)