Skip to content

Commit 7fb00a0

Browse files
SimeonCSimeonC
SimeonC
authored and
SimeonC
committedMay 23, 2015
feat(taTools): Added options for tools in taOptions
Merged #667
2 parents 5e7459e + 2c8c2c9 commit 7fb00a0

8 files changed

+172
-29
lines changed
 

‎Gruntfile.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ module.exports = function (grunt) {
113113
uglify: {
114114
options: {
115115
mangle: true,
116-
compress: true,
116+
compress: {},
117117
wrap: true,
118118
preserveComments: 'some'
119119
},

‎dist/textAngular.min.js

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

‎lib/DOM.js

+11-4
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ angular.module('textAngular.DOM', ['textAngular.factories'])
3434
};
3535
return function(taDefaultWrap, topNode){
3636
taDefaultWrap = taBrowserTag(taDefaultWrap);
37-
return function(command, showUI, options){
37+
return function(command, showUI, options, defaultTagAttributes){
3838
var i, $target, html, _nodes, next, optionsTagName, selectedElement;
3939
var defaultWrapper = angular.element('<' + taDefaultWrap + '>');
4040
try{
@@ -206,12 +206,19 @@ angular.module('textAngular.DOM', ['textAngular.factories'])
206206
taSelection.setSelectionToElementEnd($target[0]);
207207
return;
208208
}else if(command.toLowerCase() === 'createlink'){
209-
var _selection = taSelection.getSelection();
209+
var tagBegin = '<a href="' + options + '" target="' +
210+
(defaultTagAttributes.a.target ? defaultTagAttributes.a.target : '') +
211+
'">',
212+
tagEnd = '</a>',
213+
_selection = taSelection.getSelection();
210214
if(_selection.collapsed){
211215
// insert text at selection, then select then just let normal exec-command run
212-
taSelection.insertHtml('<a href="' + options + '">' + options + '</a>', topNode);
213-
return;
216+
taSelection.insertHtml(tagBegin + options + tagEnd, topNode);
217+
}else if(rangy.getSelection().getRangeAt(0).canSurroundContents()){
218+
var node = angular.element(tagBegin + tagEnd)[0];
219+
rangy.getSelection().getRangeAt(0).surroundContents(node);
214220
}
221+
return;
215222
}else if(command.toLowerCase() === 'inserthtml'){
216223
taSelection.insertHtml(options, topNode);
217224
return;

‎lib/main.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ textAngular.directive("textAngular", [
118118
scope['$redoTaBindtaTextElement' + _serial]();
119119
}else{
120120
// catch errors like FF erroring when you try to force an undo with nothing done
121-
_taExecCommand(command, false, opt);
121+
_taExecCommand(command, false, opt, scope.defaultTagAttributes);
122122
if(isSelectableElementTool){
123123
// re-apply the selectable tool events
124124
scope['reApplyOnSelectorHandlerstaTextElement' + _serial]();
@@ -134,6 +134,14 @@ textAngular.directive("textAngular", [
134134
if(attrs.taFocussedClass) scope.classes.focussed = attrs.taFocussedClass;
135135
if(attrs.taTextEditorClass) scope.classes.textEditor = attrs.taTextEditorClass;
136136
if(attrs.taHtmlEditorClass) scope.classes.htmlEditor = attrs.taHtmlEditorClass;
137+
if(attrs.taDefaultTagAttributes){
138+
try {
139+
// TODO: This should use angular.merge to enhance functionality once angular 1.4 is required
140+
angular.extend(scope.defaultTagAttributes, angular.fromJson(attrs.taDefaultTagAttributes));
141+
} catch (error) {
142+
$log.error(error);
143+
}
144+
}
137145
// optional setup functions
138146
if(attrs.taTextEditorSetup) scope.setup.textEditorSetup = scope.$parent.$eval(attrs.taTextEditorSetup);
139147
if(attrs.taHtmlEditorSetup) scope.setup.htmlEditorSetup = scope.$parent.$eval(attrs.taHtmlEditorSetup);

‎src/textAngular.js

+20-5
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ angular.module('textAngular.DOM', ['textAngular.factories'])
466466
};
467467
return function(taDefaultWrap, topNode){
468468
taDefaultWrap = taBrowserTag(taDefaultWrap);
469-
return function(command, showUI, options){
469+
return function(command, showUI, options, defaultTagAttributes){
470470
var i, $target, html, _nodes, next, optionsTagName, selectedElement;
471471
var defaultWrapper = angular.element('<' + taDefaultWrap + '>');
472472
try{
@@ -638,12 +638,19 @@ angular.module('textAngular.DOM', ['textAngular.factories'])
638638
taSelection.setSelectionToElementEnd($target[0]);
639639
return;
640640
}else if(command.toLowerCase() === 'createlink'){
641-
var _selection = taSelection.getSelection();
641+
var tagBegin = '<a href="' + options + '" target="' +
642+
(defaultTagAttributes.a.target ? defaultTagAttributes.a.target : '') +
643+
'">',
644+
tagEnd = '</a>',
645+
_selection = taSelection.getSelection();
642646
if(_selection.collapsed){
643647
// insert text at selection, then select then just let normal exec-command run
644-
taSelection.insertHtml('<a href="' + options + '">' + options + '</a>', topNode);
645-
return;
648+
taSelection.insertHtml(tagBegin + options + tagEnd, topNode);
649+
}else if(rangy.getSelection().getRangeAt(0).canSurroundContents()){
650+
var node = angular.element(tagBegin + tagEnd)[0];
651+
rangy.getSelection().getRangeAt(0).surroundContents(node);
646652
}
653+
return;
647654
}else if(command.toLowerCase() === 'inserthtml'){
648655
taSelection.insertHtml(options, topNode);
649656
return;
@@ -1904,7 +1911,7 @@ textAngular.directive("textAngular", [
19041911
scope['$redoTaBindtaTextElement' + _serial]();
19051912
}else{
19061913
// catch errors like FF erroring when you try to force an undo with nothing done
1907-
_taExecCommand(command, false, opt);
1914+
_taExecCommand(command, false, opt, scope.defaultTagAttributes);
19081915
if(isSelectableElementTool){
19091916
// re-apply the selectable tool events
19101917
scope['reApplyOnSelectorHandlerstaTextElement' + _serial]();
@@ -1920,6 +1927,14 @@ textAngular.directive("textAngular", [
19201927
if(attrs.taFocussedClass) scope.classes.focussed = attrs.taFocussedClass;
19211928
if(attrs.taTextEditorClass) scope.classes.textEditor = attrs.taTextEditorClass;
19221929
if(attrs.taHtmlEditorClass) scope.classes.htmlEditor = attrs.taHtmlEditorClass;
1930+
if(attrs.taDefaultTagAttributes){
1931+
try {
1932+
// TODO: This should use angular.merge to enhance functionality once angular 1.4 is required
1933+
angular.extend(scope.defaultTagAttributes, angular.fromJson(attrs.taDefaultTagAttributes));
1934+
} catch (error) {
1935+
$log.error(error);
1936+
}
1937+
}
19231938
// optional setup functions
19241939
if(attrs.taTextEditorSetup) scope.setup.textEditorSetup = scope.$parent.$eval(attrs.taTextEditorSetup);
19251940
if(attrs.taHtmlEditorSetup) scope.setup.htmlEditorSetup = scope.$parent.$eval(attrs.taHtmlEditorSetup);

‎src/textAngularSetup.js

+3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ angular.module('textAngularSetup', [])
2626
textEditor: 'form-control',
2727
htmlEditor: 'form-control'
2828
},
29+
defaultTagAttributes : {
30+
a: {target:""}
31+
},
2932
setup: {
3033
// wysiwyg mode
3134
textEditorSetup: function($element){ /* Do some processing here */ },

‎test/taExecCommand/taExecCommand.spec.js

+95-5
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ describe('taExecCommand', function(){
7373
expect($element.html()).toBe('bananna');
7474
}));
7575
});
76-
76+
7777
describe('catches collapsed link creation and fills them in', function(){
7878
beforeEach(function(){
7979
module(function($provide){
@@ -99,12 +99,102 @@ describe('taExecCommand', function(){
9999
});
100100
});
101101
});
102-
103-
it('correctly', inject(function(taExecCommand, taSelection){
102+
103+
it('correctly with target attribute default', inject(function(taExecCommand, taSelection){
104+
$element = angular.element('<div class="ta-bind"></div>');
105+
taSelection.element = $element[0];
106+
taExecCommand()('createLink', false, 'http://test.com', {"a":{"target":"_blank"}});
107+
expect($element.html()).toBe('<a href="http://test.com" target="_blank">http://test.com</a>');
108+
}));
109+
110+
it('correctly without target attribute default', inject(function(taExecCommand, taSelection){
104111
$element = angular.element('<div class="ta-bind"></div>');
105112
taSelection.element = $element[0];
106-
taExecCommand()('createLink', false, 'http://test.com');
107-
expect($element.html()).toBe('<a href="http://test.com">http://test.com</a>');
113+
taExecCommand()('createLink', false, 'http://test.com', {"a":{"target":""}});
114+
expect($element.html()).toBe('<a href="http://test.com" target="">http://test.com</a>');
115+
}));
116+
});
117+
118+
describe('catches NON-collapsed link creation and fills them in', function(){
119+
beforeEach(function(){
120+
module(function($provide){
121+
$provide.value('taSelection', {
122+
element: undefined,
123+
getSelection: function(){return {
124+
start: {
125+
element: this.element,
126+
offset: 2
127+
},
128+
end: {
129+
element: this.element,
130+
offset: 1
131+
},
132+
container: this.element,
133+
collapsed: false
134+
};},
135+
insertHtml: function(html){ angular.element(this.element).html(html); },
136+
getSelectionElement: function (){ return this.element; },
137+
getOnlySelectedElements: function(){ return [].slice.call(this.element.childNodes); },
138+
setSelectionToElementStart: function (){ return; },
139+
setSelectionToElementEnd: function (){ return; }
140+
});
141+
});
142+
});
143+
144+
it('correctly with target attribute default', inject(function(taExecCommand, taSelection, $window, _$document_){
145+
var sel = $window.rangy.getSelection(),
146+
range = $window.rangy.createRangyRange(),
147+
$document, contents;
148+
$document = _$document_;
149+
contents = angular.element('<div>');
150+
contents.append('<p>foo</p>');
151+
$document.find('body').append(contents);
152+
$element = contents.find('p');
153+
154+
range.selectNodeContents($element[0]);
155+
sel.setSingleRange(range);
156+
taSelection.element = $element[0];
157+
taExecCommand()('createLink', false, 'http://test.com', {"a":{"target":"_blank"}});
158+
expect($element.html()).toBe('<a href="http://test.com" target="_blank">foo</a>');
159+
}));
160+
161+
it('correctly without target attribute default', inject(function(taExecCommand, taSelection, $window, _$document_){
162+
var sel = $window.rangy.getSelection(),
163+
range = $window.rangy.createRangyRange(),
164+
$document, contents;
165+
$document = _$document_;
166+
contents = angular.element('<div>');
167+
contents.append('<p>foo</p>');
168+
$document.find('body').append(contents);
169+
$element = contents.find('p');
170+
171+
range.selectNodeContents($element[0]);
172+
sel.setSingleRange(range);
173+
taSelection.element = $element[0];
174+
taExecCommand()('createLink', false, 'http://test.com', {"a":{"target":""}});
175+
expect($element.html()).toBe('<a href="http://test.com" target="">foo</a>');
176+
}));
177+
});
178+
describe('link creation no operation path', function() {
179+
beforeEach(function(){
180+
module(function($provide){
181+
$provide.value('taSelection', {
182+
element: null,
183+
getSelection: function(){return {
184+
collapsed: false
185+
};},
186+
getSelectionElement: function (){ return this.element; }
187+
});
188+
});
189+
});
190+
191+
it('ignore createlink commands where the selection is not collapsed and cannot be surrounded', inject(function(taExecCommand, taSelection){
192+
$element = angular.element('<p>');
193+
taSelection.element = $element[0];
194+
var mock = {id:"mock", getRangeAt: function () {return {canSurroundContents: function () {return false;}};}};
195+
spyOn(rangy, "getSelection").andReturn(mock);
196+
taExecCommand()('createLink', false, 'http://test.com', {"a":{"target":""}});
197+
expect($element.html()).toBe('');
108198
}));
109199
});
110200
});

‎test/textAngular.spec.js

+30-10
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ describe('textAngular', function(){
160160
});
161161
});
162162
});
163-
163+
164164
describe('Disable the editor', function(){
165165
beforeEach(inject(function (_$compile_, _$rootScope_) {
166166
$rootScope = _$rootScope_;
@@ -187,16 +187,36 @@ describe('textAngular', function(){
187187
});
188188
});
189189
});
190-
190+
191191
it('respects the taShowHtml attribute',inject(function ($compile, $rootScope, $document) {
192-
element = $compile('<text-angular name="test" ta-show-html="true"></text-angular>')($rootScope);
193-
$document.find('body').append(element);
194-
$rootScope.$digest();
195-
expect(jQuery('.ta-text', element[0]).is(':visible')).toBe(false);
196-
expect(jQuery('.ta-html', element[0]).is(':visible')).toBe(true);
197-
element.remove();
198-
}));
199-
192+
element = $compile('<text-angular name="test" ta-show-html="true"></text-angular>')($rootScope);
193+
$document.find('body').append(element);
194+
$rootScope.$digest();
195+
expect(jQuery('.ta-text', element[0]).is(':visible')).toBe(false);
196+
expect(jQuery('.ta-html', element[0]).is(':visible')).toBe(true);
197+
element.remove();
198+
}));
199+
200+
it('respects the taDefaultTagAttributes attribute',inject(function ($compile, $rootScope, $document, textAngularManager) {
201+
$rootScope.taTestDefaultTagAttributes = {a:{target:"_blank"}, li:{test:"testing"}};
202+
element = $compile('<text-angular name="test" ta-default-tag-attributes="{{taTestDefaultTagAttributes}}"></text-angular>')($rootScope);
203+
$document.find('body').append(element);
204+
editorScope = textAngularManager.retrieveEditor('test').scope;
205+
$rootScope.$digest();
206+
expect(editorScope.defaultTagAttributes).toEqual($rootScope.taTestDefaultTagAttributes);
207+
element.remove();
208+
}));
209+
210+
it('uses the default defaultTagAttributes when the taDefaultTagAttributes attribute throws a JSON parse error',inject(function ($compile, $rootScope, $document, textAngularManager) {
211+
var taTestDefaultTagAttributes = {a:{target:""}};
212+
element = $compile('<text-angular name="test" ta-default-tag-attributes="invalidJSON"></text-angular>')($rootScope);
213+
$document.find('body').append(element);
214+
editorScope = textAngularManager.retrieveEditor('test').scope;
215+
$rootScope.$digest();
216+
expect(editorScope.defaultTagAttributes).toEqual(taTestDefaultTagAttributes);
217+
element.remove();
218+
}));
219+
200220
describe('Check view change', function(){
201221
beforeEach(inject(function (_$compile_, _$rootScope_, textAngularManager, $document) {
202222
$rootScope = _$rootScope_;

0 commit comments

Comments
 (0)