Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
feat(taTools): Added options for tools in taOptions
Merged #667
  • Loading branch information
SimeonC authored and SimeonC committed May 23, 2015
2 parents 5e7459e + 2c8c2c9 commit 7fb00a0
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 29 deletions.
2 changes: 1 addition & 1 deletion Gruntfile.js
Expand Up @@ -113,7 +113,7 @@ module.exports = function (grunt) {
uglify: {
options: {
mangle: true,
compress: true,
compress: {},
wrap: true,
preserveComments: 'some'
},
Expand Down
6 changes: 3 additions & 3 deletions dist/textAngular.min.js

Large diffs are not rendered by default.

15 changes: 11 additions & 4 deletions lib/DOM.js
Expand Up @@ -34,7 +34,7 @@ angular.module('textAngular.DOM', ['textAngular.factories'])
};
return function(taDefaultWrap, topNode){
taDefaultWrap = taBrowserTag(taDefaultWrap);
return function(command, showUI, options){
return function(command, showUI, options, defaultTagAttributes){
var i, $target, html, _nodes, next, optionsTagName, selectedElement;
var defaultWrapper = angular.element('<' + taDefaultWrap + '>');
try{
Expand Down Expand Up @@ -206,12 +206,19 @@ angular.module('textAngular.DOM', ['textAngular.factories'])
taSelection.setSelectionToElementEnd($target[0]);
return;
}else if(command.toLowerCase() === 'createlink'){
var _selection = taSelection.getSelection();
var tagBegin = '<a href="' + options + '" target="' +
(defaultTagAttributes.a.target ? defaultTagAttributes.a.target : '') +
'">',
tagEnd = '</a>',
_selection = taSelection.getSelection();
if(_selection.collapsed){
// insert text at selection, then select then just let normal exec-command run
taSelection.insertHtml('<a href="' + options + '">' + options + '</a>', topNode);
return;
taSelection.insertHtml(tagBegin + options + tagEnd, topNode);
}else if(rangy.getSelection().getRangeAt(0).canSurroundContents()){
var node = angular.element(tagBegin + tagEnd)[0];
rangy.getSelection().getRangeAt(0).surroundContents(node);
}
return;
}else if(command.toLowerCase() === 'inserthtml'){
taSelection.insertHtml(options, topNode);
return;
Expand Down
10 changes: 9 additions & 1 deletion lib/main.js
Expand Up @@ -118,7 +118,7 @@ textAngular.directive("textAngular", [
scope['$redoTaBindtaTextElement' + _serial]();
}else{
// catch errors like FF erroring when you try to force an undo with nothing done
_taExecCommand(command, false, opt);
_taExecCommand(command, false, opt, scope.defaultTagAttributes);
if(isSelectableElementTool){
// re-apply the selectable tool events
scope['reApplyOnSelectorHandlerstaTextElement' + _serial]();
Expand All @@ -134,6 +134,14 @@ textAngular.directive("textAngular", [
if(attrs.taFocussedClass) scope.classes.focussed = attrs.taFocussedClass;
if(attrs.taTextEditorClass) scope.classes.textEditor = attrs.taTextEditorClass;
if(attrs.taHtmlEditorClass) scope.classes.htmlEditor = attrs.taHtmlEditorClass;
if(attrs.taDefaultTagAttributes){
try {
// TODO: This should use angular.merge to enhance functionality once angular 1.4 is required
angular.extend(scope.defaultTagAttributes, angular.fromJson(attrs.taDefaultTagAttributes));
} catch (error) {
$log.error(error);
}
}
// optional setup functions
if(attrs.taTextEditorSetup) scope.setup.textEditorSetup = scope.$parent.$eval(attrs.taTextEditorSetup);
if(attrs.taHtmlEditorSetup) scope.setup.htmlEditorSetup = scope.$parent.$eval(attrs.taHtmlEditorSetup);
Expand Down
25 changes: 20 additions & 5 deletions src/textAngular.js
Expand Up @@ -466,7 +466,7 @@ angular.module('textAngular.DOM', ['textAngular.factories'])
};
return function(taDefaultWrap, topNode){
taDefaultWrap = taBrowserTag(taDefaultWrap);
return function(command, showUI, options){
return function(command, showUI, options, defaultTagAttributes){
var i, $target, html, _nodes, next, optionsTagName, selectedElement;
var defaultWrapper = angular.element('<' + taDefaultWrap + '>');
try{
Expand Down Expand Up @@ -638,12 +638,19 @@ angular.module('textAngular.DOM', ['textAngular.factories'])
taSelection.setSelectionToElementEnd($target[0]);
return;
}else if(command.toLowerCase() === 'createlink'){
var _selection = taSelection.getSelection();
var tagBegin = '<a href="' + options + '" target="' +
(defaultTagAttributes.a.target ? defaultTagAttributes.a.target : '') +
'">',
tagEnd = '</a>',
_selection = taSelection.getSelection();
if(_selection.collapsed){
// insert text at selection, then select then just let normal exec-command run
taSelection.insertHtml('<a href="' + options + '">' + options + '</a>', topNode);
return;
taSelection.insertHtml(tagBegin + options + tagEnd, topNode);
}else if(rangy.getSelection().getRangeAt(0).canSurroundContents()){
var node = angular.element(tagBegin + tagEnd)[0];
rangy.getSelection().getRangeAt(0).surroundContents(node);
}
return;
}else if(command.toLowerCase() === 'inserthtml'){
taSelection.insertHtml(options, topNode);
return;
Expand Down Expand Up @@ -1904,7 +1911,7 @@ textAngular.directive("textAngular", [
scope['$redoTaBindtaTextElement' + _serial]();
}else{
// catch errors like FF erroring when you try to force an undo with nothing done
_taExecCommand(command, false, opt);
_taExecCommand(command, false, opt, scope.defaultTagAttributes);
if(isSelectableElementTool){
// re-apply the selectable tool events
scope['reApplyOnSelectorHandlerstaTextElement' + _serial]();
Expand All @@ -1920,6 +1927,14 @@ textAngular.directive("textAngular", [
if(attrs.taFocussedClass) scope.classes.focussed = attrs.taFocussedClass;
if(attrs.taTextEditorClass) scope.classes.textEditor = attrs.taTextEditorClass;
if(attrs.taHtmlEditorClass) scope.classes.htmlEditor = attrs.taHtmlEditorClass;
if(attrs.taDefaultTagAttributes){
try {
// TODO: This should use angular.merge to enhance functionality once angular 1.4 is required
angular.extend(scope.defaultTagAttributes, angular.fromJson(attrs.taDefaultTagAttributes));
} catch (error) {
$log.error(error);
}
}
// optional setup functions
if(attrs.taTextEditorSetup) scope.setup.textEditorSetup = scope.$parent.$eval(attrs.taTextEditorSetup);
if(attrs.taHtmlEditorSetup) scope.setup.htmlEditorSetup = scope.$parent.$eval(attrs.taHtmlEditorSetup);
Expand Down
3 changes: 3 additions & 0 deletions src/textAngularSetup.js
Expand Up @@ -26,6 +26,9 @@ angular.module('textAngularSetup', [])
textEditor: 'form-control',
htmlEditor: 'form-control'
},
defaultTagAttributes : {
a: {target:""}
},
setup: {
// wysiwyg mode
textEditorSetup: function($element){ /* Do some processing here */ },
Expand Down
100 changes: 95 additions & 5 deletions test/taExecCommand/taExecCommand.spec.js
Expand Up @@ -73,7 +73,7 @@ describe('taExecCommand', function(){
expect($element.html()).toBe('bananna');
}));
});

describe('catches collapsed link creation and fills them in', function(){
beforeEach(function(){
module(function($provide){
Expand All @@ -99,12 +99,102 @@ describe('taExecCommand', function(){
});
});
});

it('correctly', inject(function(taExecCommand, taSelection){

it('correctly with target attribute default', inject(function(taExecCommand, taSelection){
$element = angular.element('<div class="ta-bind"></div>');
taSelection.element = $element[0];
taExecCommand()('createLink', false, 'http://test.com', {"a":{"target":"_blank"}});
expect($element.html()).toBe('<a href="http://test.com" target="_blank">http://test.com</a>');
}));

it('correctly without target attribute default', inject(function(taExecCommand, taSelection){
$element = angular.element('<div class="ta-bind"></div>');
taSelection.element = $element[0];
taExecCommand()('createLink', false, 'http://test.com');
expect($element.html()).toBe('<a href="http://test.com">http://test.com</a>');
taExecCommand()('createLink', false, 'http://test.com', {"a":{"target":""}});
expect($element.html()).toBe('<a href="http://test.com" target="">http://test.com</a>');
}));
});

describe('catches NON-collapsed link creation and fills them in', function(){
beforeEach(function(){
module(function($provide){
$provide.value('taSelection', {
element: undefined,
getSelection: function(){return {
start: {
element: this.element,
offset: 2
},
end: {
element: this.element,
offset: 1
},
container: this.element,
collapsed: false
};},
insertHtml: function(html){ angular.element(this.element).html(html); },
getSelectionElement: function (){ return this.element; },
getOnlySelectedElements: function(){ return [].slice.call(this.element.childNodes); },
setSelectionToElementStart: function (){ return; },
setSelectionToElementEnd: function (){ return; }
});
});
});

it('correctly with target attribute default', inject(function(taExecCommand, taSelection, $window, _$document_){
var sel = $window.rangy.getSelection(),
range = $window.rangy.createRangyRange(),
$document, contents;
$document = _$document_;
contents = angular.element('<div>');
contents.append('<p>foo</p>');
$document.find('body').append(contents);
$element = contents.find('p');

range.selectNodeContents($element[0]);
sel.setSingleRange(range);
taSelection.element = $element[0];
taExecCommand()('createLink', false, 'http://test.com', {"a":{"target":"_blank"}});
expect($element.html()).toBe('<a href="http://test.com" target="_blank">foo</a>');
}));

it('correctly without target attribute default', inject(function(taExecCommand, taSelection, $window, _$document_){
var sel = $window.rangy.getSelection(),
range = $window.rangy.createRangyRange(),
$document, contents;
$document = _$document_;
contents = angular.element('<div>');
contents.append('<p>foo</p>');
$document.find('body').append(contents);
$element = contents.find('p');

range.selectNodeContents($element[0]);
sel.setSingleRange(range);
taSelection.element = $element[0];
taExecCommand()('createLink', false, 'http://test.com', {"a":{"target":""}});
expect($element.html()).toBe('<a href="http://test.com" target="">foo</a>');
}));
});
describe('link creation no operation path', function() {
beforeEach(function(){
module(function($provide){
$provide.value('taSelection', {
element: null,
getSelection: function(){return {
collapsed: false
};},
getSelectionElement: function (){ return this.element; }
});
});
});

it('ignore createlink commands where the selection is not collapsed and cannot be surrounded', inject(function(taExecCommand, taSelection){
$element = angular.element('<p>');
taSelection.element = $element[0];
var mock = {id:"mock", getRangeAt: function () {return {canSurroundContents: function () {return false;}};}};
spyOn(rangy, "getSelection").andReturn(mock);
taExecCommand()('createLink', false, 'http://test.com', {"a":{"target":""}});
expect($element.html()).toBe('');
}));
});
});
40 changes: 30 additions & 10 deletions test/textAngular.spec.js
Expand Up @@ -160,7 +160,7 @@ describe('textAngular', function(){
});
});
});

describe('Disable the editor', function(){
beforeEach(inject(function (_$compile_, _$rootScope_) {
$rootScope = _$rootScope_;
Expand All @@ -187,16 +187,36 @@ describe('textAngular', function(){
});
});
});

it('respects the taShowHtml attribute',inject(function ($compile, $rootScope, $document) {
element = $compile('<text-angular name="test" ta-show-html="true"></text-angular>')($rootScope);
$document.find('body').append(element);
$rootScope.$digest();
expect(jQuery('.ta-text', element[0]).is(':visible')).toBe(false);
expect(jQuery('.ta-html', element[0]).is(':visible')).toBe(true);
element.remove();
}));

element = $compile('<text-angular name="test" ta-show-html="true"></text-angular>')($rootScope);
$document.find('body').append(element);
$rootScope.$digest();
expect(jQuery('.ta-text', element[0]).is(':visible')).toBe(false);
expect(jQuery('.ta-html', element[0]).is(':visible')).toBe(true);
element.remove();
}));

it('respects the taDefaultTagAttributes attribute',inject(function ($compile, $rootScope, $document, textAngularManager) {
$rootScope.taTestDefaultTagAttributes = {a:{target:"_blank"}, li:{test:"testing"}};
element = $compile('<text-angular name="test" ta-default-tag-attributes="{{taTestDefaultTagAttributes}}"></text-angular>')($rootScope);
$document.find('body').append(element);
editorScope = textAngularManager.retrieveEditor('test').scope;
$rootScope.$digest();
expect(editorScope.defaultTagAttributes).toEqual($rootScope.taTestDefaultTagAttributes);
element.remove();
}));

it('uses the default defaultTagAttributes when the taDefaultTagAttributes attribute throws a JSON parse error',inject(function ($compile, $rootScope, $document, textAngularManager) {
var taTestDefaultTagAttributes = {a:{target:""}};
element = $compile('<text-angular name="test" ta-default-tag-attributes="invalidJSON"></text-angular>')($rootScope);
$document.find('body').append(element);
editorScope = textAngularManager.retrieveEditor('test').scope;
$rootScope.$digest();
expect(editorScope.defaultTagAttributes).toEqual(taTestDefaultTagAttributes);
element.remove();
}));

describe('Check view change', function(){
beforeEach(inject(function (_$compile_, _$rootScope_, textAngularManager, $document) {
$rootScope = _$rootScope_;
Expand Down

0 comments on commit 7fb00a0

Please sign in to comment.