');n.taToolbar&&D.attr("ta-toolbar",n.taToolbar),n.taToolbarClass&&D.attr("ta-toolbar-class",n.taToolbarClass),n.taToolbarGroupClass&&D.attr("ta-toolbar-group-class",n.taToolbarGroupClass),n.taToolbarButtonClass&&D.attr("ta-toolbar-button-class",n.taToolbarButtonClass),n.taToolbarActiveButtonClass&&D.attr("ta-toolbar-active-button-class",n.taToolbarActiveButtonClass),n.taFocussedClass&&D.attr("ta-focussed-class",n.taFocussedClass),m.prepend(D),a(D)(l.$parent),w=f.registerEditor(l._name,l,["textAngularToolbar"+y])}l.$on("$destroy",function(){f.unregisterEditor(l._name)}),l.$on("ta-element-select",function(a,b){w.triggerElementSelect(a,b)&&l["reApplyOnSelectorHandlerstaTextElement"+y]()}),l.$on("ta-drop-event",function(a,c,d,e){l.displayElements.text[0].focus(),e&&e.files&&e.files.length>0?(angular.forEach(e.files,function(a){try{k.when(l.fileDropHandler(a,l.wrapSelection)||l.fileDropHandler!==l.defaultFileDropHandler&&k.when(l.defaultFileDropHandler(a,l.wrapSelection))).then(function(){l["updateTaBindtaTextElement"+y]()})}catch(b){j.error(b)}}),d.preventDefault(),d.stopPropagation()):b(function(){l["updateTaBindtaTextElement"+y]()},0)}),l._bUpdateSelectedStyles=!1,l.updateSelectedStyles=function(){var a;void 0!==(a=d.getSelectionElement())&&a.parentNode!==l.displayElements.text[0]?w.updateSelectedStyles(angular.element(a)):w.updateSelectedStyles(),l._bUpdateSelectedStyles&&b(l.updateSelectedStyles,200)},p=function(){l._bUpdateSelectedStyles||(l._bUpdateSelectedStyles=!0,l.$apply(function(){l.updateSelectedStyles()}))},l.displayElements.html.on("keydown",p),l.displayElements.text.on("keydown",p),q=function(){l._bUpdateSelectedStyles=!1},l.displayElements.html.on("keyup",q),l.displayElements.text.on("keyup",q),r=function(a,b){b&&angular.extend(a,b),l.$apply(function(){return w.sendKeyCommand(a)?(l._bUpdateSelectedStyles||l.updateSelectedStyles(),a.preventDefault(),!1):void 0})},l.displayElements.html.on("keypress",r),l.displayElements.text.on("keypress",r),s=function(){l._bUpdateSelectedStyles=!1,l.$apply(function(){l.updateSelectedStyles()})},l.displayElements.html.on("mouseup",s),l.displayElements.text.on("mouseup",s)}}}]),q.service("textAngularManager",["taToolExecuteAction","taTools","taRegisterTool",function(a,b,c){var d={},e={};return{registerEditor:function(c,f,g){if(!c||""===c)throw"textAngular Error: An editor requires a name";if(!f)throw"textAngular Error: An editor requires a scope";if(e[c])throw'textAngular Error: An Editor with name "'+c+'" already exists';var h=[];return angular.forEach(g,function(a){d[a]&&h.push(d[a])}),e[c]={scope:f,toolbars:g,_registerToolbar:function(a){this.toolbars.indexOf(a.name)>=0&&h.push(a)},editorFunctions:{disable:function(){angular.forEach(h,function(a){a.disabled=!0})},enable:function(){angular.forEach(h,function(a){a.disabled=!1})},focus:function(){angular.forEach(h,function(a){a._parent=f,a.disabled=!1,a.focussed=!0})},unfocus:function(){angular.forEach(h,function(a){a.disabled=!0,a.focussed=!1})},updateSelectedStyles:function(a){angular.forEach(h,function(b){angular.forEach(b.tools,function(c){c.activeState&&(b._parent=f,c.active=c.activeState(a))})})},sendKeyCommand:function(c){var d=!1;return(c.ctrlKey||c.metaKey)&&angular.forEach(b,function(b,e){if(b.commandKeyCode&&b.commandKeyCode===c.which)for(var g=0;g
0)for(var k=0;k"),d.addClass(b&&b["class"]?b["class"]:g.classes.toolbarButton),d.attr("name",c.name),d.attr("unselectable","on"),d.attr("ng-disabled","isDisabled()"),d.attr("tabindex","-1"),d.attr("ng-click","executeAction()"),d.attr("ng-class","displayActiveToolClass(active)"),b&&b.tooltiptext&&d.attr("title",b.tooltiptext),d.on("mousedown",function(a,b){return b&&angular.extend(a,b),a.preventDefault(),!1}),b&&!b.display&&!c._display&&(d[0].innerHTML="",b.buttontext&&(d[0].innerHTML=b.buttontext),b.iconclass)){var e=angular.element(""),f=d[0].innerHTML;e.addClass(b.iconclass),d[0].innerHTML="",d.append(e),f&&""!==f&&d.append(" "+f)}return c._lastToolDefinition=angular.copy(b),a(d)(c)};g.tools={},g._parent={disabled:!0,showHtml:!1,queryFormatBlockState:function(){return!1},queryCommandState:function(){return!1}};var k={$window:f,$editor:function(){return g._parent},isDisabled:function(){return"function"!=typeof this.$eval("disabled")&&this.$eval("disabled")||this.$eval("disabled()")||"html"!==this.name&&this.$editor().showHtml||this.$parent.disabled||this.$editor().disabled},displayActiveToolClass:function(a){return a?g.classes.toolbarButtonActive:""},executeAction:e};angular.forEach(g.toolbar,function(a){var b=angular.element("");b.addClass(g.classes.toolbarGroup),angular.forEach(a,function(a){g.tools[a]=angular.extend(g.$new(!0),d[a],k,{name:a}),g.tools[a].$element=j(d[a],g.tools[a]),b.append(g.tools[a].$element)}),h.append(b)}),g.updateToolDisplay=function(a,b,c){var d=g.tools[a];if(d){if(d._lastToolDefinition&&!c&&(b=angular.extend({},d._lastToolDefinition,b)),null===b.buttontext&&null===b.iconclass&&null===b.display)throw'textAngular Error: Tool Definition for updating "'+a+'" does not have a valid display/iconclass/buttontext value';null===b.buttontext&&delete b.buttontext,null===b.iconclass&&delete b.iconclass,null===b.display&&delete b.display;var e=j(b,d);d.$element.replaceWith(e),d.$element=e}},g.addTool=function(a,b,c,e){g.tools[a]=angular.extend(g.$new(!0),d[a],k,{name:a}),g.tools[a].$element=j(d[a],g.tools[a]);var f;void 0===c&&(c=g.toolbar.length-1),f=angular.element(h.children()[c]),void 0===e?(f.append(g.tools[a].$element),g.toolbar[c][g.toolbar[c].length-1]=a):(f.children().eq(e).after(g.tools[a].$element),g.toolbar[c][e]=a)},b.registerToolbar(g),g.$on("$destroy",function(){b.unregisterToolbar(g.name)})}}}])}()}({},function(){return this}());
\ No newline at end of file
diff --git a/lib/DOM.js b/lib/DOM.js
index a9d01bc6..c68970e3 100644
--- a/lib/DOM.js
+++ b/lib/DOM.js
@@ -323,11 +323,13 @@ function($window, $document){
}
}
for(var _n = 0; _n < nodes.length; _n++) lastNode = frag.appendChild(nodes[_n]);
+ if(!isInline && range.collapsed && /^(|
)$/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();
diff --git a/lib/taBind.js b/lib/taBind.js
index 68af4113..1f4bd563 100644
--- a/lib/taBind.js
+++ b/lib/taBind.js
@@ -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(/([\s\S]*?)/i);
if(!textFragment) textFragment = text;
@@ -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("
" + text + "
");
+ _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('
', '');
+ }
+ }else if(text.match(/^
]*?>/ig, '');
+ }
+ text = text.replace(/
]*?>/ig, '');
}
text = taSanitize(text, '', _disableSanitizer);
diff --git a/src/textAngular.js b/src/textAngular.js
index d067fcd0..9bebf335 100644
--- a/src/textAngular.js
+++ b/src/textAngular.js
@@ -606,11 +606,13 @@ function($window, $document){
}
}
for(var _n = 0; _n < nodes.length; _n++) lastNode = frag.appendChild(nodes[_n]);
+ if(!isInline && range.collapsed && /^(|
)$/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();
@@ -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(/([\s\S]*?)/i);
if(!textFragment) textFragment = text;
@@ -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("" + text + "
");
+ _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('
', '');
+ }
+ }else if(text.match(/^]*?>/ig, '');
+ }
+ text = text.replace(/
]*?>/ig, '');
}
text = taSanitize(text, '', _disableSanitizer);
diff --git a/test/taBind/taBind.events.spec.js b/test/taBind/taBind.events.spec.js
index fe4538ae..3bc27f2a 100644
--- a/test/taBind/taBind.events.spec.js
+++ b/test/taBind/taBind.events.spec.js
@@ -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 'Test 4 Content'; }}});
+ element.triggerHandler('paste', {clipboardData: {types: ['text/html'], getData: function(){ return 'Test 4 Content'; }}});
$timeout.flush();
$rootScope.$digest();
- expect($rootScope.html).toBe('Test 4 Content
');
+ expect($rootScope.html).toBe('Test 4 Content
');
}));
it('non-ie based w/ jquery', inject(function($window){
- element.triggerHandler('paste', {originalEvent: {clipboardData: {types: ['text/html'], getData: function(){ return 'Test 4 Content';} }}});
+ element.triggerHandler('paste', {originalEvent: {clipboardData: {types: ['text/html'], getData: function(){ return 'Test 4 Content';} }}});
$timeout.flush();
$rootScope.$digest();
- expect($rootScope.html).toBe('Test 4 Content
');
+ expect($rootScope.html).toBe('Test 4 Content
');
}));
});