/*! * * jQuery TE 1.4.0 , http://jqueryte.com/ * Copyright (C) 2013, Fatih Koca (fattih@fattih.com), (http://jqueryte.com/about) * jQuery TE is provided under the MIT LICENSE. * */ (function($){ $.fn.jqte = function(options){ // default titles of buttons var varsTitle = [ { title:"Text Format" }, { title:"Font Size" }, { title:"Color" }, { title:"Bold",hotkey:"B" }, { title:"Italic",hotkey:"I" }, { title:"Underline",hotkey:"U" }, { title:"Ordered List",hotkey:"." }, { title:"Unordered List",hotkey:"," }, { title:"Subscript",hotkey:"down arrow" }, { title:"Superscript",hotkey:"up arrow" }, { title:"Outdent",hotkey:"left arrow" }, { title:"Indent",hotkey:"right arrow" }, { title:"Justify Left" }, { title:"Justify Center" }, { title:"Justify Right" }, { title:"Strike Through",hotkey:"K" }, { title:"Add Link",hotkey:"L" }, { title:"Remove Link" }, { title:"Cleaner Style",hotkey:"Delete" }, { title:"Horizontal Rule",hotkey:"H" }, { title:"Source" }, ]; // default text formats var formats = [["p","Normal"],["h1","Header 1"],["h2","Header 2"],["h3","Header 3"],["h4","Header 4"],["h5","Header 5"],["h6","Header 6"],["pre","Preformatted"]]; // default font sizes var fsizes = ["10","12","16","18","20","24","28"]; // default rgb values of colors var colors = [ "0,0,0","68,68,68","102,102,102","153,153,153","204,204,204","238,238,238","243,243,243","255,255,255", null, "255,0,0","255,153,0","255,255,0","0,255,0","0,255,255","0,0,255","153,0,255","255,0,255", null, "244,204,204","252,229,205","255,242,204","217,234,211","208,224,227","207,226,243","217,210,233","234,209,220", "234,153,153","249,203,156","255,229,153","182,215,168","162,196,201","159,197,232","180,167,214","213,166,189", "224,102,102","246,178,107","255,217,102","147,196,125","118,165,175","111,168,220","142,124,195","194,123,160", "204,0,0","230,145,56","241,194,50","106,168,79","69,129,142","61,133,198","103,78,167","166,77,121", "153,0,0","180,95,6","191,144,0","56,118,29","19,79,92","11,83,148","53,28,117","116,27,71", "102,0,0","120,63,4","127,96,0","39,78,19","12,52,61","7,55,99","32,18,77","76,17,48", ]; // default link-type names var linktypes = ["Web Address","E-mail Address","Picture URL"]; var vars = $.extend({ // options 'status' : true, 'css' : "jqte", 'title' : true, 'titletext' : varsTitle, 'button' : "OK", 'format' : true, formats, 'fsize' : true, fsizes, 'funit' : "px", 'color' : true, linktypes, 'b' : true, 'i' : true, 'u' : true, 'ol' : true, 'ul' : true, 'sub' : true, 'sup' : true, 'outdent' : true, 'indent' : true, 'left' : true, 'center' : true, 'right' : true, 'strike' : true, 'link' : true, 'unlink' : true, 'remove' : true, 'rule' : true, 'source' : true, 'placeholder' : false, 'br' : true, 'p' : true, // events 'change' : "", 'focus' : "", 'blur' : "", }, options); // methods $.fn.jqteVal = function(value){ $(this).closest(`.${vars.css}`).find(`.${vars.css}_editor`).html(value); } // browser information is received var thisBrowser = navigator.userAgent.toLowerCase(); // if browser is ie and it version is 7 or even older, close title property if(/msie [1-7]./.test(thisBrowser)) vars.title = false; var buttons = []; // insertion function for parameters to toolbar function addParams(name,command,key,tag,emphasis) { var thisCssNo = buttons.length+1; return buttons.push({ name, cls:thisCssNo, command, key, tag, emphasis }); }; // add parameters for toolbar buttons addParams('format','formats','','',false); // text format button --> no hotkey addParams('fsize','fSize','','',false); // font size button --> no hotkey addParams('color','colors','','',false); // text color button --> no hotkey addParams('b','Bold','B',["b","strong"],true); // bold --> ctrl + b addParams('i','Italic','I',["i","em"],true); // italic --> ctrl + i addParams('u','Underline','U',["u"],true); // underline --> ctrl + u addParams('ol','insertorderedlist','¾',["ol"],true); // ordered list --> ctrl + .(dot) addParams('ul','insertunorderedlist','¼',["ul"],true); // unordered list --> ctrl + ,(comma) addParams('sub','subscript','(',["sub"],true); // sub script --> ctrl + down arrow addParams('sup','superscript','&',["sup"],true); // super script --> ctrl + up arrow addParams('outdent','outdent','%',["blockquote"],false); // outdent --> ctrl + left arrow addParams('indent','indent','\'',["blockquote"],true); // indent --> ctrl + right arrow addParams('left','justifyLeft','','',false); // justify Left --> no hotkey addParams('center','justifyCenter','','',false); // justify center --> no hotkey addParams('right','justifyRight','','',false); // justify right --> no hotkey addParams('strike','strikeThrough','K',["strike"],true); // strike through --> ctrl + K addParams('link','linkcreator','L',["a"],true); // insertion link --> ctrl + L addParams('unlink','unlink','',["a"],false); // remove link --> ctrl + N addParams('remove','removeformat','.','',false); // remove all styles --> ctrl + delete addParams('rule','inserthorizontalrule','H',["hr"],false); // insertion horizontal rule --> ctrl + H addParams('source','displaysource','','',false); // feature of displaying source return this.each(function(){ if(!$(this).data("jqte") || $(this).data("jqte")==null || $(this).data("jqte")=="undefined") $(this).data("jqte",true); else $(this).data("jqte",false); // is the status false of the editor if(!vars.status || !$(this).data("jqte")) { // if wanting the false status later if($(this).closest(`.${vars.css}`).length>0) { var editorValue = $(this).closest(`.${vars.css}`).find(`.${vars.css}_editor`).html(); // add all attributes of element var thisElementAttrs = ""; $($(this)[0].attributes).each(function() { if(this.nodeName!="style") thisElementAttrs = `${thisElementAttrs} ${this.nodeName}="${this.nodeValue}"`; }); var thisElementTag = $(this).is("[data-origin]") && $(this).attr("data-origin")!="" ? $(this).attr("data-origin") : "textarea"; // the contents of this element var createValue = `>${editorValue}`; // if this element is input or option if(thisElementTag=="input" || thisElementTag=="option") { // encode special html characters editorValue = editorValue.replace(/"/g,'"').replace(/'/g,''').replace(//g,'>'); // the value of this element createValue = `value="${editorValue}">`; } var thisClone = $(this).clone(); $(this).data("jqte",false).closest(`.${vars.css}`).before(thisClone).remove(); thisClone.replaceWith(`<${ thisElementTag }${thisElementAttrs }${createValue }`); } return; } // element will converted to the jqte editor var thisElement = $(this); // tag name of the element var thisElementTag = $(this).prop('tagName').toLowerCase(); // tag name of origin $(this).attr("data-origin",thisElementTag); // contents of the element var thisElementVal = $(this).is("[value]") || thisElementTag == "textarea" ? $(this).val() : $(this).html(); // decode special html characters thisElementVal = thisElementVal.replace(/"/g,'"').replace(/'/g,"'").replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&'); // start jqte editor to after the element $(this).after(`
`); // jqte var jQTE = $(this).next(`.${vars.css}`); // insert toolbar in jqte editor jQTE.html(`
`); var toolbar = jQTE.find(`.${vars.css}_toolbar`); // the toolbar variable var linkform = jQTE.find(`.${vars.css}_linkform`); // the link-form-area in the toolbar variable var editor = jQTE.find(`.${vars.css}_editor`); // the text-field of jqte editor var emphasize = `${vars.css}_tool_depressed`; // highlight style of the toolbar buttons // add to some tools in link form area linkform.append(`
${vars.button}
`); var linktypeselect = linkform.find(`.${vars.css}_linktypeselect`); // the tool of link-type-selector var linkinput = linkform.find(`.${vars.css}_linkinput`); // the input of insertion link var linkbutton = linkform.find(`.${vars.css}_linkbutton`); // the button of insertion link // add to the link-type-selector sub tool parts linktypeselect.append(`
`); var linktypes = linktypeselect.find(`.${vars.css}_linktypes`); // the select box of link types var linktypeview = linktypeselect.find(`.${vars.css}_linktypeview`); // the link type preview var setdatalink = `${vars.css}-setlink`; // the selected text add to mark as "link will be added" // create to the source-area editor.after(`
`); var sourceField = jQTE.find(`.${vars.css}_source`); // the source-area variable // move the element to the source-area thisElement.appendTo(sourceField); // if the element isn't a textarea, convert this to textarea if(thisElementTag!="textarea") { // add all attributes of element to new textarea (type and value except) var thisElementAttrs = ""; $(thisElement[0].attributes).each(function(){ if(this.nodeName!="type" && this.nodeName!="value") thisElementAttrs = `${thisElementAttrs} ${this.nodeName}="${this.nodeValue}"`; }); // convert the element to textarea thisElement.replaceWith(``); // update to variable of thisElement thisElement = sourceField.find("textarea"); } // add feature editable to the text-field ve copy from the element's value to text-field editor.attr("contenteditable","true").html(thisElementVal); // insertion the toolbar button for(var n = 0; n < buttons.length; n++) { // if setting of this button is activated (is it true?) if(vars[buttons[n].name]) { // if it have a title, add to this button var buttonHotkey = buttons[n].key.length>0 ? vars.titletext[n].hotkey!=null && vars.titletext[n].hotkey!="undefined" && vars.titletext[n].hotkey!="" ? ` (Ctrl+${vars.titletext[n].hotkey})` : '' : ''; var buttonTitle = vars.titletext[n].title!=null && vars.titletext[n].title!="undefined" && vars.titletext[n].title!="" ? vars.titletext[n].title+buttonHotkey : ''; // add this button to the toolbar toolbar.append(`
`); // add the parameters to this button toolbar.find(`.${vars.css}_tool[data-tool=${n}]`).data({ tag : buttons[n].tag, command : buttons[n].command, emphasis : buttons[n].emphasis, title : buttonTitle }); // format-selector field if(buttons[n].name=="format" && $.isArray(vars.formats)) { // selected text format var toolLabel = vars.formats[0][1].length>0 && vars.formats[0][1]!="undefined" ? vars.formats[0][1] : ""; toolbar.find(`.${vars.css}_tool_${buttons[n].cls}`).find(`.${vars.css}_tool_icon`).replaceWith(`${toolLabel}`); toolbar.find(`.${vars.css}_tool_${buttons[n].cls}`) .append(`
`); // add font-sizes to font-size-selector for(var f = 0; f < vars.formats.length; f++) { toolbar.find(`.${vars.css}_formats`).append(`${ vars.formats[f][1] }`); } toolbar.find(`.${vars.css}_formats`).data("status",false); } // font-size-selector field else if(buttons[n].name=="fsize" && $.isArray(vars.fsizes)) { toolbar.find(`.${vars.css}_tool_${buttons[n].cls}`) .append(`
`); // add font-sizes to font-size-selector for(var f = 0; f < vars.fsizes.length; f++) { toolbar.find(`.${vars.css}_fontsizes`).append(`Abcdefgh...`); } } // color-selector field else if(buttons[n].name=="color" && $.isArray(colors)) { toolbar.find(`.${vars.css}_tool_${buttons[n].cls}`) .append(`
`); // create color palette to color-selector field for(var c = 0; c < colors.length; c++) { if(colors[c]!=null) toolbar.find(`.${vars.css}_cpalette`).append(``); else toolbar.find(`.${vars.css}_cpalette`).append(`
`); } } } } // the default value of the link-type linktypes.data("linktype","0"); // add link types to link-type-selector for(var n = 0; n < 3; n++) { linktypes.append(`${vars.linktypes[n]}`); linktypeview.html(`
${linktypes.find(`a:eq(${linktypes.data("linktype")})`).text()}
`); } // add the prefix of css according to browser var prefixCss = ""; if(/msie/.test(thisBrowser)) // ie prefixCss = '-ms-'; else if(/chrome/.test(thisBrowser) || /safari/.test(thisBrowser) || /yandex/.test(thisBrowser)) // webkit group (safari, chrome, yandex) prefixCss = '-webkit-'; else if(/mozilla/.test(thisBrowser)) // firefox prefixCss = '-moz-'; else if(/opera/.test(thisBrowser)) // opera prefixCss = '-o-'; else if(/konqueror/.test(thisBrowser)) // konqueror prefixCss = '-khtml-'; else prefixCss = ''; // the feature of placeholder if(vars.placeholder && vars.placeholder!="") { jQTE.prepend(`
${vars.placeholder}
`); var placeHolder = jQTE.find(`.${vars.css}_placeholder`); placeHolder.click(() => { editor.focus(); }); } // make unselectable to unselectable attribute ones jQTE.find("[unselectable]") .css(`${prefixCss}user-select`,"none") .addClass("unselectable") .attr("unselectable","on") .on("selectstart mousedown",false); // each button of the toolbar var toolbutton = toolbar.find(`.${vars.css}_tool`); // format menu var formatbar = toolbar.find(`.${vars.css}_formats`); // font-size filed var fsizebar = toolbar.find(`.${vars.css}_fontsizes`); // color palette var cpalette = toolbar.find(`.${vars.css}_cpalette`); // get the selected text as plain format function selectionGet() { // for webkit, mozilla, opera if (window.getSelection) return window.getSelection(); // for ie else if (document.selection && document.selection.createRange && document.selection.type != "None") return document.selection.createRange(); } // the function of changing to the selected text with "execCommand" method function selectionSet(addCommand,thirdParam) { var range, sel = selectionGet(); // for webkit, mozilla, opera if (window.getSelection) { if (sel.anchorNode && sel.getRangeAt) range = sel.getRangeAt(0); if(range) { sel.removeAllRanges(); sel.addRange(range); } if(!thisBrowser.match(/msie/)) document.execCommand('StyleWithCSS', false, false); document.execCommand(addCommand, false, thirdParam); } // for ie else if (document.selection && document.selection.createRange && document.selection.type != "None") { range = document.selection.createRange(); range.execCommand(addCommand, false, thirdParam); } // change styles to around tags affectStyleAround(false,false); } // the function of changing to the selected text with tags and tags's attributes function replaceSelection(tTag,tAttr,tVal) { // first, prevent to conflict of different jqte editors if(editor.not(":focus")) editor.focus(); // for webkit, mozilla, opera if (window.getSelection) { var selObj = selectionGet(), selRange, newElement, documentFragment; if (selObj.anchorNode && selObj.getRangeAt) { selRange = selObj.getRangeAt(0); // create to new element newElement = document.createElement(tTag); // add the attribute to the new element $(newElement).attr(tAttr,tVal); // extract to the selected text documentFragment = selRange.extractContents(); // add the contents to the new element newElement.appendChild(documentFragment); selRange.insertNode(newElement); selObj.removeAllRanges(); // if the attribute is "style", change styles to around tags if(tAttr=="style") affectStyleAround($(newElement),tVal); // for other attributes else affectStyleAround($(newElement),false); } } // for ie else if (document.selection && document.selection.createRange && document.selection.type != "None") { var range = document.selection.createRange(); var selectedText = range.htmlText; var newText = `<${tTag} ${tAttr}="${tVal}">${selectedText}`; document.selection.createRange().pasteHTML(newText); } } // the function of getting to the parent tag var getSelectedNode = function() { var node,selection; if(window.getSelection) { selection = getSelection(); node = selection.anchorNode; } if(!node && document.selection && document.selection.createRange && document.selection.type != "None") { selection = document.selection; var range = selection.getRangeAt ? selection.getRangeAt(0) : selection.createRange(); node = range.commonAncestorContainer ? range.commonAncestorContainer : range.parentElement ? range.parentElement() : range.item(0); } if(node) { return (node.nodeName == "#text" ? $(node.parentNode) : $(node)); } else return false; }; // the function of replacement styles to the around tags (parent and child) function affectStyleAround(element,style) { var selectedTag = getSelectedNode(); // the selected node selectedTag = selectedTag ? selectedTag : element; // (for replacement with execCommand) affect to child tags with parent tag's styles if(selectedTag && style==false) { // apply to the selected node with parent tag's styles if(selectedTag.parent().is("[style]")) selectedTag.attr("style",selectedTag.parent().attr("style")); // apply to child tags with parent tag's styles if(selectedTag.is("[style]")) selectedTag.find("*").attr("style",selectedTag.attr("style")); } // (for replacement with html changing method) else if(element && style && element.is("[style]")) { var styleKey = style.split(";"); // split the styles styleKey = styleKey[0].split(":") // get the key of first style feature // apply to child tags with parent tag's styles if(element.is(`[style*=${styleKey[0]}]`)) element.find("*").css(styleKey[0],styleKey[1]); // select to the selected node again selectText(element); } } // the function of making selected to a element function selectText(element) { if(element) { var element = element[0]; if (document.body.createTextRange) { var range = document.body.createTextRange(); range.moveToElementText(element); range.select(); } else if (window.getSelection) { var selection = window.getSelection(); var range = document.createRange(); if(element != "undefined" && element != null) { range.selectNodeContents(element); selection.removeAllRanges(); selection.addRange(range); if($(element).is(":empty")) { $(element).append(" "); selectText($(element)); } } } } } // the function of converting text to link function selected2link() { if(!toolbar.data("sourceOpened")) { var selectedTag = getSelectedNode(); // the selected node var thisHrefLink = "http://"; // default the input value of the link-form-field // display the link-form-field linkAreaSwitch(true); if(selectedTag) { var thisTagName = selectedTag.prop('tagName').toLowerCase(); // if tag name of the selected node is "a" and the selected node have "href" attribute if(thisTagName == "a" && selectedTag.is('[href]')) { thisHrefLink = selectedTag.attr('href'); selectedTag.attr(setdatalink,""); } // if it don't have "a" tag name else replaceSelection("a",setdatalink,""); } else linkinput.val(thisHrefLink).focus(); // the method of displaying-hiding to link-types linktypeselect.click((e) => { if($(e.target).hasClass(`${vars.css}_linktypetext`) || $(e.target).hasClass(`${vars.css}_linktypearrow`)) linktypeSwitch(true); }); // the method of selecting to link-types linktypes.find("a").click(function() { var thisLinkType = $(this).attr(`${vars.css}-linktype`); linktypes.data("linktype",thisLinkType) linktypeview.find(`.${vars.css}_linktypetext`).html(linktypes.find(`a:eq(${linktypes.data("linktype")})`).text()); linkInputSet(thisHrefLink); linktypeSwitch(); }); linkInputSet(thisHrefLink); // the method of link-input linkinput // auto focus .focus() // update to value .val(thisHrefLink) // the event of key to enter in link-input .bind("keypress keyup",(e) => { if(e.keyCode==13) { linkRecord(jQTE.find(`[${setdatalink}]`)); return false; } }); // the event of click link-button linkbutton.click(() => { linkRecord(jQTE.find(`[${setdatalink}]`)); }); } else // hide the link-form-field linkAreaSwitch(false); } function linkRecord(thisSelection) { // focus to link-input linkinput.focus(); // select to the selected node selectText(thisSelection); // remove pre-link attribute (mark as "link will be added") of the selected node thisSelection.removeAttr(setdatalink); // if not selected to link-type of picture if(linktypes.data("linktype")!="2") selectionSet("createlink",linkinput.val()); // insert link url of link-input to the selected node // if selected to link-type of picture else { selectionSet("insertImage",linkinput.val()); // insert image url of link-input to the selected node // the method of all pictures in the editor editor.find("img").each(function(){ var emptyPrevLinks = $(this).prev("a"); var emptyNextLinks = $(this).next("a"); // if "a" tags of the front and rear of the picture is empty, remove if(emptyPrevLinks.length>0 && emptyPrevLinks.html()=="") emptyPrevLinks.remove(); else if(emptyNextLinks.length>0 && emptyNextLinks.html()=="") emptyNextLinks.remove(); }); } // hide the link-form-field linkAreaSwitch(); // export contents of the text to the sources editor.trigger("change"); } // the function of switching link-form-field function linkAreaSwitch(status) { // remove all pre-link attribute (mark as "link will be added") clearSetElement(`[${setdatalink}]:not([href])`); jQTE.find(`[${setdatalink}][href]`).removeAttr(setdatalink); if(status) { toolbar.data("linkOpened",true); linkform.show(); } else { toolbar.data("linkOpened",false); linkform.hide(); } linktypeSwitch(); } // the function of switching link-type-selector function linktypeSwitch(status) { if(status) linktypes.show(); else linktypes.hide(); } // the function of updating the link-input according to the link-type function linkInputSet(thisHrefLink) { var currentType = linktypes.data("linktype"); // if selected type of e-mail if(currentType=="1" && (linkinput.val()=="http://" || linkinput.is("[value^=http://]") || !linkinput.is("[value^=mailto]"))) linkinput.val("mailto:"); else if(currentType!="1" && !linkinput.is("[value^=http://]")) linkinput.val("http://"); else linkinput.val(thisHrefLink); } // the function of adding style to selected text function selected2style(styleCommand) { if(!toolbar.data("sourceOpened")) { // if selected to changing the font-size value if(styleCommand=="fSize") styleField = fsizebar; // if selected to changing the text-color value else if(styleCommand=="colors") styleField = cpalette; // display the style-field styleFieldSwitch(styleField,true); // the event of click to style button styleField.find("a").unbind("click").click(function() { var styleValue = $(this).attr(`${vars.css }-styleval`); // the property of style value to be added // if selected to changing the font-size value if(styleCommand=="fSize") { styleType = "font-size"; styleValue = styleValue + vars.funit; // combine the value with size unit } // if selected to changing the text-color value else if(styleCommand=="colors") { styleType = "color"; styleValue = `rgb(${styleValue })`; // combine color value with rgb } var prevStyles = refuseStyle(styleType); // affect styles to child tags (and extract to the new style attributes) // change to selected text replaceSelection("span","style",`${styleType}:${styleValue};${prevStyles}`); // hide all style-fields styleFieldSwitch("",false); // remove title bubbles $(`.${vars.css}_title`).remove(); // export contents of the text to the sources editor.trigger("change"); }); } else // hide the style-field styleFieldSwitch(styleField,false); // hide the link-form-field linkAreaSwitch(false); } // the function of switching the style-field function styleFieldSwitch(styleField,status) { var mainData="", // the style data of the actual wanted allData = [{ "d":"fsizeOpened","f":fsizebar },{ "d":"cpallOpened","f":cpalette }]; // all style datas // if the style data of the actual wanted isn't empty if(styleField!="") { // return to all datas and find the main data for(var si=0; si < allData.length; si++) { if(styleField==allData[si]["f"]) mainData = allData[si]; } } // display the style-field if(status) { toolbar.data(mainData["d"],true); // stil seçme alanının açıldığını belirten parametre yaz mainData["f"].slideDown(100); // stil seçme alanını aç // return to all datas and close the fields of external datas for(var si=0; si < allData.length; si++) { if(mainData["d"]!=allData[si]["d"]) { toolbar.data(allData[si]["d"],false); allData[si]["f"].slideUp(100); } } } // hide all style-fields else { // return to all datas and close all style fields for(var si=0; si < allData.length; si++) { toolbar.data(allData[si]["d"],false); allData[si]["f"].slideUp(100); } } } // the function of removing all pre-link attribute (mark as "link will be added") function clearSetElement(elem) { jQTE.find(elem).each(function(){ $(this).before($(this).html()).remove(); }); } // the function of refusing some styles function refuseStyle(refStyle) { var selectedTag = getSelectedNode(); // the selected node // if the selected node have attribute of "style" and it have unwanted style if(selectedTag && selectedTag.is("[style]") && selectedTag.css(refStyle)!="") { var refValue = selectedTag.css(refStyle); // first get key of unwanted style selectedTag.css(refStyle,""); // clear unwanted style var cleanStyle = selectedTag.attr("style"); // cleaned style selectedTag.css(refStyle,refValue); // add unwanted style to the selected node again return cleanStyle; // print cleaned style } else return ""; } // the function of adding style to selected text function selected2format() { formatFieldSwitch(true); formatbar.find("a").click(function() { $("*",this).click((e) => { e.preventDefault(); return false; }); formatLabelView($(this).text()); var formatValue = $(this).attr(`${vars.css }-formatval`); // the type of format value // convert to selected format selectionSet("formatBlock",`<${formatValue}>`); formatFieldSwitch(false); }); } // the function of switching the style-field function formatFieldSwitch(status) { var thisStatus = status ? true : false; thisStatus = status && formatbar.data("status") ? true : false; if(thisStatus || !status) formatbar.data("status",false).slideUp(200); else formatbar.data("status",true).slideDown(200); } // change format label function formatLabelView(str) { var formatLabel = formatbar.closest(`.${vars.css}_tool`).find(`.${vars.css}_tool_label`).find(`.${vars.css}_tool_text`); if(str.length > 10) str = `${str.substr(0,7) }...`; // change format label of button formatLabel.html(str); } // the function of insertion a specific form to texts function extractToText(strings) { var $htmlContent, $htmlPattern, $htmlReplace; // first remove to unnecessary gaps $htmlContent = strings.replace(/\n/gim,'').replace(/\r/gim,'').replace(/\t/gim,'').replace(/ /gim,' '); $htmlPattern = [ /\(.*?)<\/span><\/span>/gim, // trim nested spans /<(\w*[^p])\s*[^\/>]*>\s*<\/\1>/gim, // remove empty or white-spaces tags (ignore paragraphs (

) and breaks (
)) /\(.*?)\<\/div>/gim, // convert div to p /\(.*?)\<\/strong>/gim, // convert strong to b /\(.*?)\<\/em>/gim, // convert em to i ]; $htmlReplace = [ '$3', '', '$2

', '$2', '$2', ]; // repeat the cleaning process 5 times for(c=0; c<5; c++) { // create loop as the number of pattern for(var i = 0; i < $htmlPattern.length; i++) { $htmlContent = $htmlContent.replace($htmlPattern[i], $htmlReplace[i]); } } // if paragraph is false (

), convert

to
if(!vars.p) $htmlContent = $htmlContent.replace(/\(.*?)\<\/p>/ig, '
$2'); // if break is false (
), convert
to

if(!vars.br) { $htmlPattern = [ /\
(.*?)/ig, /\(.*?)/ig, ]; $htmlReplace = [ '

$1

', '

$1

', ]; // create loop as the number of pattern (for breaks) for (var i = 0; i < $htmlPattern.length; i++) { $htmlContent = $htmlContent.replace($htmlPattern[i], $htmlReplace[i]); } } // if paragraph and break is false (

&&
), convert

to

if(!vars.p && !vars.br) $htmlContent = $htmlContent.replace(/\

(.*?)\<\/p>/ig, '

$1
'); return $htmlContent; } // the function of exporting contents of the text field to the source field (to be the standard in all browsers) function postToSource() { // clear unnecessary tags when editor view empty var sourceStrings = editor.text()=="" && editor.html().length<12 ? "" : editor.html(); thisElement.val(extractToText(sourceStrings)); } // the function of exporting contents of the source field to the text field (to be the standard in all browsers) function postToEditor() { editor.html(extractToText(thisElement.val())); } // the function of getting parent (or super parent) tag name of the selected node function detectElement(tags){ var resultdetect=false, $node = getSelectedNode(), parentsTag; if($node) { $.each(tags, (i, val) => { parentsTag = $node.prop('tagName').toLowerCase(); if (parentsTag == val) resultdetect = true; else { $node.parents().each(function(){ parentsTag = $(this).prop('tagName').toLowerCase(); if (parentsTag == val) resultdetect = true; }); } }); return resultdetect; } else return false; }; // the function of highlighting the toolbar buttons according to the cursor position in jqte editor function buttonEmphasize(e) { for(var n = 0; n < buttons.length; n++) { if(vars[buttons[n].name] && buttons[n].emphasis && buttons[n].tag!='') detectElement(buttons[n].tag) ? toolbar.find(`.${vars.css}_tool_${buttons[n].cls}`).addClass(emphasize) : $(`.${vars.css}_tool_${buttons[n].cls}`).removeClass(emphasize); } // showing text format if(vars.format && $.isArray(vars.formats)) { var isFoundFormat = false; for(var f = 0; f < vars.formats.length; f++) { var thisFormat = []; thisFormat[0] = vars.formats[f][0]; if(vars.formats[f][0].length>0 && detectElement(thisFormat)) { formatLabelView(vars.formats[f][1]); isFoundFormat = true; break; } } if(!isFoundFormat) formatLabelView(vars.formats[0][1]); } // hide all style-fields styleFieldSwitch("",false); formatFieldSwitch(false); } // the event of click to the toolbar buttons toolbutton .unbind("click") .click(function(e){ // if source button is clicked if($(this).data('command')=='displaysource' && !toolbar.data("sourceOpened")) { // hide all the toolbar buttons (except the source button) toolbar.find(`.${vars.css}_tool`).addClass(`${vars.css}_hiddenField`); $(this).removeClass(`${vars.css}_hiddenField`); // update to data of source displaying toolbar.data("sourceOpened",true); // equalize height of the text field with height of the source field thisElement.css("height",editor.outerHeight()); sourceField.removeClass(`${vars.css}_hiddenField`); editor.addClass(`${vars.css}_hiddenField`); thisElement.focus(); // hide the link-form-field linkAreaSwitch(false); // hide all style-fields styleFieldSwitch("",false); // hide format field formatFieldSwitch(); // hide placeholder if(vars.placeholder && vars.placeholder!="") placeHolder.hide(); } // if other buttons is clicked else { // if source field is closed if(!toolbar.data("sourceOpened")) { // if insert-link-button is clicked if($(this).data('command')=='linkcreator') { if(!toolbar.data("linkOpened")) selected2link(); else { // hide the link-form-field linkAreaSwitch(false); // hide format field formatFieldSwitch(false); } } // if the format button is clicked else if($(this).data('command')=='formats') { if($(this).data('command')=='formats' && !$(e.target).hasClass(`${vars.css}_format`)) selected2format(); // hide all style-fields styleFieldSwitch("",false); if(editor.not(":focus")) editor.focus(); } // if the style buttons are clicked else if($(this).data('command')=='fSize' || $(this).data('command')=='colors') { if( ($(this).data('command')=='fSize' && !$(e.target).hasClass(`${vars.css}_fontsize`)) || // the font-size button ($(this).data('command')=='colors' && !$(e.target).hasClass(`${vars.css}_color`)) // the color button ) selected2style($(this).data('command')); // hide format field formatFieldSwitch(false); if(editor.not(":focus")) editor.focus(); } // if other buttons is clicked else { // first, prevent to conflict of different jqte editors if(editor.not(":focus")) editor.focus(); // apply command of clicked button to the selected text selectionSet($(this).data('command'),null); // hide all menu-fields styleFieldSwitch("",false); formatFieldSwitch(false); linktypeSwitch(); // to highlight the toolbar buttons according to the cursor position in jqte editor $(this).data('emphasis')==true && !$(this).hasClass(emphasize) ? $(this).addClass(emphasize) : $(this).removeClass(emphasize); sourceField.addClass(`${vars.css}_hiddenField`); editor.removeClass(`${vars.css}_hiddenField`); } } // hide the source field and display the text field else { // update to data of source hiding toolbar.data("sourceOpened",false); // display all the toolbar buttons toolbar.find(`.${vars.css}_tool`).removeClass(`${vars.css}_hiddenField`); sourceField.addClass(`${vars.css}_hiddenField`); editor.removeClass(`${vars.css}_hiddenField`); } if(vars.placeholder && vars.placeholder!="") editor.html()!="" ? placeHolder.hide() : placeHolder.show(); } // export contents of the text to the sources editor.trigger("change"); }) // the event of showing to the title bubble when mouse over of the toolbar buttons .hover(function(e){ if(vars.title && $(this).data("title")!="" && ( $(e.target).hasClass(`${vars.css}_tool`) || $(e.target).hasClass(`${vars.css}_tool_icon`) )) { $(`.${vars.css}_title`).remove(); // create the title bubble jQTE.append(`
${$(this).data("title")}
`); var thisTitle = $(`.${vars.css}_title:first`); var thisArrow = thisTitle.find(`.${vars.css}_titleArrowIcon`); var thisPosition = $(this).position(); var thisAlignX = thisPosition.left + $(this).outerWidth() - (thisTitle.outerWidth()/2) - ($(this).outerWidth()/2); var thisAlignY = (thisPosition.top + $(this).outerHeight() + 5); // show the title bubble and set to its position thisTitle.delay(400).css({ 'top':thisAlignY, 'left':thisAlignX }).fadeIn(200); } },() => { $(`.${vars.css}_title`).remove(); }); // prevent multiple calling postToSource() var editorChangeTimer = null; // the methods of the text fields editor // trigger change method of the text field when the text field modified .bind("keypress keyup keydown drop cut copy paste DOMCharacterDataModified DOMSubtreeModified",function() { // export contents of the text to the sources if(!toolbar.data("sourceOpened")) $(this).trigger("change"); // hide the link-type-field linktypeSwitch(); // if the change method is added run the change method if($.isFunction(vars.change)) vars.change(); // the feature of placeholder if(vars.placeholder && vars.placeholder!="") $(this).text()!="" ? placeHolder.hide() : placeHolder.show(); }) .bind("change",() => { if(!toolbar.data("sourceOpened")) { clearTimeout(editorChangeTimer); editorChangeTimer = setTimeout(postToSource,10); } }) // run to keyboard shortcuts .keydown((e) => { // if ctrl key is clicked if(e.ctrlKey) { // check all toolbar buttons for(var n = 0; n < buttons.length; n++) { // if this settings of this button is activated (is it true) // if the keyed button with ctrl is same of hotkey of this button if(vars[buttons[n].name] && e.keyCode == buttons[n].key.charCodeAt(0)) { if(buttons[n].command!='' && buttons[n].command!='linkcreator') selectionSet(buttons[n].command,null); else if(buttons[n].command=='linkcreator') selected2link(); return false; } } } }) // method of triggering to the highlight button .bind("mouseup keyup",buttonEmphasize) // the event of focus to the text field .focus(() => { // if the focus method is added run the focus method if($.isFunction(vars.focus)) vars.focus(); // add onfocus class jQTE.addClass(`${vars.css}_focused`); // prevent focus problem on opera if(/opera/.test(thisBrowser)) { var range = document.createRange(); range.selectNodeContents(editor[0]); range.collapse(false); var selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(range); } }) // the event of focus out from the text field .focusout(() => { // remove to highlights of all toolbar buttons toolbutton.removeClass(emphasize); // hide all menu-fields styleFieldSwitch("",false); formatFieldSwitch(false); linktypeSwitch(); // if the blur method is added run the blur method if($.isFunction(vars.blur)) vars.blur(); // remove onfocus class jQTE.removeClass(`${vars.css}_focused`); // show default text format if($.isArray(vars.formats)) formatLabelView(vars.formats[0][1]); }); // the event of key in the source field thisElement .bind("keydown keyup",function() { // export contents of the source to the text field setTimeout(postToEditor,0); // auto extension for the source field $(this).height($(this)[0].scrollHeight); // if the source field is empty, shorten to the source field if($(this).val()=="") $(this).height(0); }) .focus(() => { // add onfocus class jQTE.addClass(`${vars.css}_focused`); }) .focusout(() => { // remove onfocus class jQTE.removeClass(`${vars.css}_focused`); }); }); }; })(jQuery);