This repository was archived by the owner on Nov 13, 2023. It is now read-only.
forked from textAngular/textAngular
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtextAngular.min.js
More file actions
1 lines (1 loc) · 13.1 KB
/
textAngular.min.js
File metadata and controls
1 lines (1 loc) · 13.1 KB
1
var textAngular=angular.module("textAngular",["ngSanitize"]);textAngular.directive("textAngular",function($compile,$sce,$window,$document,$rootScope,$timeout,taFixChrome){console.log("Thank you for using textAngular! http://www.textangular.com");function deepExtend(destination,source){for(var property in source){if(source[property]&&source[property].constructor&&source[property].constructor===Object){destination[property]=destination[property]||{};arguments.callee(destination[property],source[property])}else{destination[property]=source[property]}}return destination}$rootScope.textAngularOpts=deepExtend({toolbar:[["h1","h2","h3","p","pre","bold","italics","ul","ol","redo","undo","clear"],["html","insertImage","insertLink"]],classes:{toolbar:"btn-toolbar",toolbarGroup:"btn-group",toolbarButton:"btn btn-default",toolbarButtonActive:"active",textEditor:"form-control",htmlEditor:"form-control"}},$rootScope.textAngularOpts!=null?$rootScope.textAngularOpts:{});$rootScope.textAngularTools=deepExtend({html:{display:"<button type='button' ng-click='action()' ng-class='displayActiveToolClass(active)'>Toggle HTML</button>",action:function(){var ht,_this=this;this.$parent.showHtml=!this.$parent.showHtml;if(this.$parent.showHtml){$timeout(function(){return _this.$parent.displayElements.html[0].focus()},100)}else{$timeout(function(){return _this.$parent.displayElements.text[0].focus()},100)}this.active=this.$parent.showHtml}},h1:{display:"<button type='button' ng-click='action()' ng-class='displayActiveToolClass(active)'>H1</button>",action:function(){return this.$parent.wrapSelection("formatBlock","<H1>")}},h2:{display:"<button type='button' ng-click='action()' ng-class='displayActiveToolClass(active)'>H2</button>",action:function(){return this.$parent.wrapSelection("formatBlock","<H2>")}},h3:{display:"<button type='button' ng-click='action()' ng-class='displayActiveToolClass(active)'>H3</button>",action:function(){return this.$parent.wrapSelection("formatBlock","<H3>")}},p:{display:"<button type='button' ng-click='action()' ng-class='displayActiveToolClass(active)'>P</button>",action:function(){return this.$parent.wrapSelection("formatBlock","<P>")}},pre:{display:"<button type='button' ng-click='action()' ng-class='displayActiveToolClass(active)'>pre</button>",action:function(){return this.$parent.wrapSelection("formatBlock","<PRE>")}},ul:{display:"<button type='button' ng-click='action()' ng-class='displayActiveToolClass(active)'><i class='fa fa-list-ul'></i></button>",action:function(){return this.$parent.wrapSelection("insertUnorderedList",null)}},ol:{display:"<button type='button' ng-click='action()' ng-class='displayActiveToolClass(active)'><i class='fa fa-list-ol'></i></button>",action:function(){return this.$parent.wrapSelection("insertOrderedList",null)}},quote:{display:"<button type='button' ng-click='action()' ng-class='displayActiveToolClass(active)'><i class='fa fa-quote-right'></i></button>",action:function(){return this.$parent.wrapSelection("formatBlock","<BLOCKQUOTE>")}},undo:{display:"<button type='button' ng-click='action()' ng-class='displayActiveToolClass(active)'><i class='fa fa-undo'></i></button>",action:function(){return this.$parent.wrapSelection("undo",null)}},redo:{display:"<button type='button' ng-click='action()' ng-class='displayActiveToolClass(active)'><i class='fa fa-repeat'></i></button>",action:function(){return this.$parent.wrapSelection("redo",null)}},bold:{display:"<button type='button' ng-click='action()' ng-class='displayActiveToolClass(active)'><i class='fa fa-bold'></i></button>",action:function(){return this.$parent.wrapSelection("bold",null)},activeState:function(){return $document[0].queryCommandState("bold")}},justifyLeft:{display:"<button type='button' ng-click='action()' ng-class='displayActiveToolClass(active)'><i class='fa fa-align-left'></i></button>",action:function(){return this.$parent.wrapSelection("justifyLeft",null)},activeState:function(){return $document[0].queryCommandState("justifyLeft")}},justifyRight:{display:"<button type='button' ng-click='action()' ng-class='displayActiveToolClass(active)'><i class='fa fa-align-right'></i></button>",action:function(){return this.$parent.wrapSelection("justifyRight",null)},activeState:function(){return $document[0].queryCommandState("justifyRight")}},justifyCenter:{display:"<button type='button' ng-click='action()' ng-class='displayActiveToolClass(active)'><i class='fa fa-align-center'></i></button>",action:function(){return this.$parent.wrapSelection("justifyCenter",null)},activeState:function(){return $document[0].queryCommandState("justifyCenter")}},italics:{display:"<button type='button' ng-click='action()' ng-class='displayActiveToolClass(active)'><i class='fa fa-italic'></i></button>",action:function(){return this.$parent.wrapSelection("italic",null)},activeState:function(){return $document[0].queryCommandState("italic")}},clear:{display:"<button type='button' ng-click='action()' ng-class='displayActiveToolClass(active)'><i class='fa fa-ban'></i></button>",action:function(){return this.$parent.wrapSelection("FormatBlock","<div>")}},insertImage:{display:"<button type='button' ng-click='action()' ng-class='displayActiveToolClass(active)'><i class='fa fa-picture-o'></i></button>",action:function(){var imageLink;imageLink=prompt("Please enter an image URL to insert","http://");if(imageLink!==""){return this.$parent.wrapSelection("insertImage",imageLink)}}},insertLink:{display:"<button type='button' ng-click='action()' ng-class='displayActiveToolClass(active)'><i class='fa fa-chain'></i></button>",action:function(){var urlLink;urlLink=prompt("Please enter an URL to insert","http://");if(urlLink!==""){return this.$parent.wrapSelection("createLink",urlLink)}}}},$rootScope.textAngularTools!=null?$rootScope.textAngularTools:{});return{require:"ngModel",scope:{},restrict:"EA",link:function(scope,element,attrs,ngModel){var group,groupElement,keydown,keyup,tool,toolElement;angular.extend(scope,$rootScope.textAngularOpts,{wrapSelection:function(command,opt){document.execCommand(command,false,opt);if(command==="insertUnorderedList"||command==="insertOrderedList")taFixChrome(scope.displayElements.text);if(scope.showHtml)scope.displayElements.html[0].focus();else scope.displayElements.text[0].focus();if(!scope.showHtml)scope.updateTaBindtext()},showHtml:false});if(!!attrs.taToolbar)scope.toolbar=scope.$eval(attrs.taToolbar);if(!!attrs.taToolbarClass)scope.classes.toolbar=attrs.taToolbarClass;if(!!attrs.taToolbarGroupClass)scope.classes.toolbarGroup=attrs.taToolbarGroupClass;if(!!attrs.taToolbarButtonClass)scope.classes.toolbarButton=attrs.taToolbarButtonClass;if(!!attrs.taToolbarActiveButtonClass)scope.classes.toolbarButtonActive=attrs.taToolbarActiveButtonClass;if(!!attrs.taTextEditorClass)scope.classes.textEditor=attrs.taTextEditorClass;if(!!attrs.taHtmlEditorClass)scope.classes.htmlEditor=attrs.taHtmlEditorClass;scope.displayElements={toolbar:angular.element("<div></div>"),html:angular.element("<pre contentEditable='true' ng-show='showHtml' ta-bind='html' ng-model='html' ></pre>"),text:angular.element("<div contentEditable='true' ng-hide='showHtml' ta-bind='text' ng-model='text' ></div>")};element.append(scope.displayElements.toolbar);element.append(scope.displayElements.text);element.append(scope.displayElements.html);$compile(scope.displayElements.text)(scope);$compile(scope.displayElements.html)(scope);element.addClass("ta-root");scope.displayElements.toolbar.addClass("ta-toolbar "+scope.classes.toolbar);scope.displayElements.text.addClass("ta-text ta-editor "+scope.classes.textEditor);scope.displayElements.html.addClass("ta-html ta-editor "+scope.classes.textEditor);scope.tools={};for(var _i=0;_i<scope.toolbar.length;_i++){group=scope.toolbar[_i];groupElement=angular.element("<div></div>");groupElement.addClass(scope.classes.toolbarGroup);for(var _j=0;_j<group.length;_j++){tool=group[_j];toolElement=angular.element($rootScope.textAngularTools[tool].display);toolElement.addClass(scope.classes.toolbarButton);toolElement.attr("unselectable","on");toolElement.attr("ng-disabled","showHtml()");var childScope=angular.extend(scope.$new(true),$rootScope.textAngularTools[tool],{name:tool,showHtml:function(){if(this.name!=="html")return this.$parent.showHtml;return false},displayActiveToolClass:function(active){return active?this.$parent.classes.toolbarButtonActive:""}});scope.tools[tool]=childScope;groupElement.append($compile(toolElement)(childScope))}scope.displayElements.toolbar.append(groupElement)}ngModel.$render=function(){if(ngModel.$viewValue===undefined)return;if(!($document[0].activeElement===scope.displayElements.html[0])&&!($document[0].activeElement===scope.displayElements.text[0])){var val=ngModel.$viewValue||"";scope.text=val;scope.html=val}};scope.$watch("text",function(newValue,oldValue){scope.html=newValue;ngModel.$setViewValue(newValue)});scope.$watch("html",function(newValue,oldValue){scope.text=newValue;ngModel.$setViewValue(newValue)});scope.bUpdateSelectedStyles=false;scope.updateSelectedStyles=function(){for(var _k=0;_k<scope.toolbar.length;_k++){var groups=scope.toolbar[_k];for(var _l=0;_l<groups.length;_l++){tool=groups[_l];if(scope.tools[tool].activeState!=null){scope.tools[tool].active=scope.tools[tool].activeState.apply(scope)}}}if(this.bUpdateSelectedStyles)$timeout(this.updateSelectedStyles,200)};keydown=function(e){scope.bUpdateSelectedStyles=true;scope.$apply(function(){scope.updateSelectedStyles()})};scope.displayElements.html.on("keydown",keydown);scope.displayElements.text.on("keydown",keydown);keyup=function(e){scope.bUpdateSelectedStyles=false};scope.displayElements.html.on("keyup",keyup);scope.displayElements.text.on("keyup",keyup);mouseup=function(e){scope.$apply(function(){scope.updateSelectedStyles()})};scope.displayElements.html.on("mouseup",mouseup);scope.displayElements.text.on("mouseup",mouseup)}}}).directive("taBind",function($sce,$sanitize,$document,taFixChrome){var sanitizationWrapper=function(html){return $sce.trustAsHtml(html)};return{require:"ngModel",scope:{taBind:"@"},link:function(scope,element,attrs,ngModel){var compileHtml=function(){var result=taFixChrome(angular.element("<div>").append(element.html())).html();if(scope.taBind!=="text")result=result.replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&");return result};scope.$parent["updateTaBind"+scope.taBind]=function(){var compHtml=compileHtml();var tempParsers=ngModel.$parsers;ngModel.$parsers=[];ngModel.$oldViewValue=compHtml;ngModel.$setViewValue(compHtml);ngModel.$parsers=tempParsers};element.on("keyup",function(e){ngModel.$setViewValue(compileHtml())});ngModel.$parsers.push(function(value){if(ngModel.$oldViewValue===undefined)ngModel.$oldViewValue=value;if(scope.taBind==="text"&&value!==ngModel.$oldViewValue){if(value===undefined||value==="")return value;var end;for(end=0;end<Math.min(value.length,ngModel.$oldViewValue.length);end++){var oldViewEnd=ngModel.$oldViewValue.length-end;if(value.charAt(value.length-end)!==ngModel.$oldViewValue.charAt(oldViewEnd)){if(value.charAt(value.length-end)==="<"&&ngModel.$oldViewValue.substring(oldViewEnd-4,oldViewEnd)==="<"||value.charAt(value.length-end)===">"&&ngModel.$oldViewValue.substring(oldViewEnd-4,oldViewEnd)===">"){value=value.substring(0,value.length-end)+ngModel.$oldViewValue.substring(oldViewEnd-4,oldViewEnd)+value.substring(value.length-end+1);end+=3}else break}else if(value.charAt(value.length-end)===">"&&value.substring(value.length-end-1,value.length-end+1)===">>")break}var start;for(start=0;start<Math.min(value.length,ngModel.$oldViewValue.length)&&Math.min(value.length,ngModel.$oldViewValue.length)-end>start;start++){if(value.charAt(start)!==ngModel.$oldViewValue.charAt(start)){if(value.charAt(start)==="<"&&ngModel.$oldViewValue.substring(start,start+4)==="<"||value.charAt(start)===">"&&ngModel.$oldViewValue.substring(start,start+4)===">"){value=value.substring(0,start)+ngModel.$oldViewValue.substring(start,start+4)+value.substring(start+1);start+=3}else break}else if(value.charAt(start)==="<"&&value.substring(start,start+2)==="<<")break}var insert=value.substring(start,value.length-end+1);if(insert.match(/[<>]/gi)&&insert.length<=3||insert.match(/^[<>]+$/gi)){value=value.substring(0,start)+insert.replace(/</g,"<").replace(/>/g,">")+value.substring(value.length-end+1);ngModel.$oldViewValue=value;ngModel.$setViewValue(value)}}else{try{$sanitize(value)}catch(e){return ngModel.$oldViewValue}}ngModel.$oldViewValue=value;return value});ngModel.$render=function(){if(ngModel.$viewValue===undefined)return;if($document[0].activeElement!==element[0]){var val=ngModel.$viewValue||"";ngModel.$oldViewValue=val;if(scope.taBind=="text")element.html(sanitizationWrapper(val));else element.html(sanitizationWrapper(val.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")))}}}}}).factory("taFixChrome",function(){var taFixChrome=function($html){var spans=angular.element($html).find("span");for(var s=0;s<spans.length;s++){var span=angular.element(spans[s]);if(span.attr("style")&&span.attr("style").match(/line-height: 1.428571429;/i)){if(span.next().length>0&&span.next()[0].tagName==="BR")span.next().remove();span.replaceWith(span.html())}}var result=$html.html().replace(/style="[^"]*?line-height: 1.428571429;[^"]*"/gi,"");$html.html(result);return $html};return taFixChrome});