123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947 |
- (function ( $ ) {
-
- $.fn.richText = function( options ) {
- // set default options
- // and merge them with the parameter options
- var settings = $.extend({
- //id
- //id: "",
- // text formatting
- bold: true,
- italic: true,
- underline: true,
- // text alignment
- leftAlign: true,
- centerAlign: true,
- rightAlign: true,
- justify: true,
- // lists
- ol: true,
- ul: true,
- // title
- heading: false,
- // fonts
- fonts: false,
- fontList: ["Arial",
- "Arial Black",
- "Comic Sans MS",
- "Courier New",
- "Geneva",
- "Georgia",
- "Helvetica",
- "Impact",
- "Lucida Console",
- "Tahoma",
- "Times New Roman",
- "Verdana"
- ],
- fontColor: false,
- fontSize: false,
- // uploads
- imageUpload: false,
- fileUpload: false,
- // media
- videoEmbed: false,
- // link
- urls: false,
- // tables
- table: false,
- // code
- removeStyles: false,
- code: false,
- // colors
- colors: [],
- // dropdowns
- fileHTML: '',
- imageHTML: '',
- // translations
- translations: {
- 'title': 'Título',
- 'white': 'Blanco',
- 'black': 'Negro',
- 'brown': 'Café',
- 'beige': 'Beige',
- 'darkBlue': 'Azul Marino',
- 'blue': 'Azul',
- 'lightBlue': 'Azul Claro',
- 'darkRed': 'Rojo Obscuro',
- 'red': 'Rojo',
- 'darkGreen': 'Verde Obscuro',
- 'green': 'Verde',
- 'purple': 'Morado',
- 'darkTurquois': 'Turquesa Obscuro',
- 'turquois': 'Turquesa',
- 'darkOrange': 'naranja Obscuro',
- 'orange': 'Naranja',
- 'yellow': 'Amarillo',
- 'imageURL': 'URL Imagen',
- 'fileURL': 'URL Archivo',
- 'linkText': 'Hipervínculo',
- 'url': 'URL',
- 'size': 'Tamaño',
- 'responsive': 'Responsivo',
- 'text': 'Texto',
- 'openIn': 'Abrir en',
- 'sameTab': 'Misma página',
- 'newTab': 'Nueva Página',
- 'align': 'Alinear',
- 'left': 'Izquierda',
- 'justify': 'Justificado',
- 'center': 'Centrado',
- 'right': 'Derecha',
- 'rows': 'Renglones',
- 'columns': 'Columnas',
- 'add': 'Agregar',
- 'pleaseEnterURL': 'Ingresa una URL',
- 'videoURLnotSupported': 'URL de video no soportado',
- 'pleaseSelectImage': 'Seleccione una imagen',
- 'pleaseSelectFile': 'Seleccione un archivo',
- 'bold': 'Negrita',
- 'italic': 'Cursiva',
- 'underline': 'Subrayado',
- 'alignLeft': 'Alinear a la izquierda',
- 'alignCenter': 'Alinear centrado',
- 'alignRight': 'Alinear a la derecha',
- 'addOrderedList': 'Numeración',
- 'addUnorderedList': 'Viñetas',
- 'addHeading': 'Títulos',
- 'addFont': 'Cambiar fuente',
- 'addFontColor': 'Cambiar color de fuente',
- 'addFontSize' : 'Cambiar tamaño de fuente',
- 'addImage': 'Agregar imagen',
- 'addVideo': 'Agregar video',
- 'addFile': 'Agregar archivo',
- 'addURL': 'Vínculo',
- 'addTable': 'Tabla',
- 'removeStyles': 'Remover estilos',
- 'code': 'Mostrar código',
- 'undo': 'Deshacer',
- 'redo': 'Repetir',
- 'close': 'Cerrar'
- },
- // privacy
- youtubeCookies: false,
- // dev settings
- useSingleQuotes: false,
- height: 0,
- heightPercentage: 0,
- id: "",
- class: "",
- useParagraph: false
- }, options );
- /* prepare toolbar */
- var $inputElement = $(this);
- $inputElement.addClass("richText-initial");
- var $editor,
- $toolbarList = $('<ul />'),
- $toolbarElement = $('<li />'),
- $btnBold = $('<a />', {class: "richText-btn", "data-command": "bold", "title": settings.translations.bold, html: '<span class="fa fa-bold"></span>'}), // bold
- $btnItalic = $('<a />', {class: "richText-btn", "data-command": "italic", "title": settings.translations.italic, html: '<span class="fa fa-italic"></span>'}), // italic
- $btnUnderline = $('<a />', {class: "richText-btn", "data-command": "underline", "title": settings.translations.underline, html: '<span class="fa fa-underline"></span>'}), // underline
- $btnJustify = $('<a />', {class: "richText-btn", "data-command": "justifyFull", "title": settings.translations.justify, html: '<span class="fa fa-align-justify"></span>'}), // left align
- $btnLeftAlign = $('<a />', {class: "richText-btn", "data-command": "justifyLeft", "title": settings.translations.alignLeft, html: '<span class="fa fa-align-left"></span>'}), // left align
- $btnCenterAlign = $('<a />', {class: "richText-btn", "data-command": "justifyCenter", "title": settings.translations.alignCenter, html: '<span class="fa fa-align-center"></span>'}), // centered
- $btnRightAlign = $('<a />', {class: "richText-btn", "data-command": "justifyRight", "title": settings.translations.alignRight, html: '<span class="fa fa-align-right"></span>'}), // right align
- $btnOL = $('<a />', {class: "richText-btn", "data-command": "insertOrderedList", "title": settings.translations.addOrderedList, html: '<span class="fa fa-list-ol"></span>'}), // ordered list
- $btnUL = $('<a />', {class: "richText-btn", "data-command": "insertUnorderedList", "title": settings.translations.addUnorderedList, html: '<span class="fa fa-list"></span>'}), // unordered list
- $btnHeading = $('<a />', {class: "richText-btn", "title": settings.translations.addHeading, html: '<span class="fa fa-header fa-heading"></span>'}), // title/header
- $btnFont = $('<a />', {class: "richText-btn", "title": settings.translations.addFont, html: '<span class="fa fa-font"></span>'}), // font color
- $btnFontColor = $('<a />', {class: "richText-btn", "title": settings.translations.addFontColor, html: '<span class="fa fa-paint-brush"></span>'}), // font color
- $btnFontSize = $('<a />', {class: "richText-btn", "title": settings.translations.addFontSize, html: '<span class="fa fa-text-height"></span>'}), // font color
- $btnImageUpload = $('<a />', {class: "richText-btn", "title": settings.translations.addImage, html: '<span class="fa fa-image"></span>'}), // image
- $btnVideoEmbed = $('<a />', {class: "richText-btn", "title": settings.translations.addVideo, html: '<span class="fa fa-video-camera fa-video"></span>'}), // video
- $btnFileUpload = $('<a />', {class: "richText-btn", "title": settings.translations.addFile, html: '<span class="fa fa-file-text-o far fa-file-alt"></span>'}), // file
- $btnURLs = $('<a />', {class: "richText-btn", "title": settings.translations.addURL, html: '<span class="fa fa-link"></span>'}), // urls/links
- $btnTable = $('<a />', {class: "richText-btn", "title": settings.translations.addTable, html: '<span class="fa fa-table"></span>'}), // table
- $btnRemoveStyles = $('<a />', {class: "richText-btn", "data-command": "removeFormat", "title": settings.translations.removeStyles, html: '<span class="fa fa-recycle"></span>'}), // clean up styles
- $btnCode = $('<a />', {class: "richText-btn ocultar", "data-command": "toggleCode", "title": settings.translations.code, html: '<span class="fa fa-code"></span>'}); // code
- $btnUndo = $('<a />', {class: 'richText-undo is-disabled', html: '<span class="fa fa-undo"></span>', 'title': settings.translations.undo}); //undo
- $btnRedo = $('<a />', {class: 'richText-redo is-disabled', html: '<span class="fa fa-repeat fa-redo"></span>', 'title': settings.translations.redo});//redo
-
- /* prepare toolbar dropdowns */
- var $dropdownOuter = $('<div />', {class: "richText-dropdown-outer"});
- var $dropdownClose = $('<span />', {class: "richText-dropdown-close", html: '<span title="' + settings.translations.close + '"><span class="fa fa-times"></span></span>'});
- var $dropdownList = $('<ul />', {class: "richText-dropdown"}), // dropdown lists
- $dropdownBox = $('<div />', {class: "richText-dropdown"}), // dropdown boxes / custom dropdowns
- $form = $('<div />', {class: "richText-form"}), // symbolic form
- $formItem = $('<div />', {class: 'richText-form-item'}), // form item
- $formLabel = $('<label />'), // form label
- $formInput = $('<input />', {type: "text"}), //form input field
- $formRadio = $('<input />', {type: "radio"}), //form input field
- $formInputFile = $('<input />', {type: "file"}), // form file input field
- $formInputSelect = $('<select />'),
- $formButton = $('<button />', {text: settings.translations.add, class: "btn btn-accept"}); // button
- /* internal settings */
- var savedSelection; // caret position/selection
- var editorID = "richText-" + Math.random().toString(36).substring(7);
- //var editorID = settings.id;
- var ignoreSave = false, $resizeImage = null;
- /* prepare editor history */
- var history = [];
- history[editorID] = [];
- var historyPosition = [];
- historyPosition[editorID] = 0;
- /* list dropdown for titles */
- var $titles = $dropdownList.clone();
- $titles.append($('<li />', {html: '<a data-command="formatBlock" data-option="h1">' + settings.translations.title + ' #1</a>'}));
- $titles.append($('<li />', {html: '<a data-command="formatBlock" data-option="h2">' + settings.translations.title + ' #2</a>'}));
- $titles.append($('<li />', {html: '<a data-command="formatBlock" data-option="h3">' + settings.translations.title + ' #3</a>'}));
- $titles.append($('<li />', {html: '<a data-command="formatBlock" data-option="h4">' + settings.translations.title + ' #4</a>'}));
- $btnHeading.append($dropdownOuter.clone().append($titles.prepend($dropdownClose.clone())));
- /* list dropdown for fonts */
- var fonts = settings.fontList;
- var $fonts = $dropdownList.clone();
- for(var i = 0; i < fonts.length; i++) {
- $fonts.append($('<li />', {html: '<a style="font-family:' + fonts[i] + ';" data-command="fontName" data-option="' + fonts[i] + '">' + fonts[i] + '</a>'}));
- }
- $btnFont.append($dropdownOuter.clone().append($fonts.prepend($dropdownClose.clone())));
- /* list dropdown for font sizes */
- var fontSizes = [24,18,16,14,12];
- var $fontSizes = $dropdownList.clone();
- for(var i = 0; i < fontSizes.length; i++) {
- $fontSizes.append($('<li />', {html: '<a style="font-size:' + fontSizes[i] + 'px;" data-command="fontSize" data-option="' + fontSizes[i] + '">Text ' + fontSizes[i] + 'px</a>'}));
- }
- $btnFontSize.append($dropdownOuter.clone().append($fontSizes.prepend($dropdownClose.clone())));
- /* font colors */
- var $fontColors = $dropdownList.clone();
- $fontColors.html(loadColors("forecolor"));
- $btnFontColor.append($dropdownOuter.clone().append($fontColors.prepend($dropdownClose.clone())));
- /* background colors */
- //var $bgColors = $dropdownList.clone();
- //$bgColors.html(loadColors("hiliteColor"));
- //$btnBGColor.append($dropdownOuter.clone().append($bgColors));
- /* box dropdown for links */
- var $linksDropdown = $dropdownBox.clone();
- var $linksForm = $form.clone().attr("id", "richText-URL").attr("data-editor", editorID);
- $linksForm.append(
- $formItem.clone().addClass('my-2')
- .append($formLabel.clone().text(settings.translations.url).attr("for", "url").addClass('col-lg-3'))
- .append($formInput.clone().attr("id", "url"))
- );
- $linksForm.append(
- $formItem.clone().addClass('my-2')
- .append($formLabel.clone().text(settings.translations.text).attr("for", "urlText").addClass('col-lg-3'))
- .append($formInput.clone().attr("id", "urlText"))
- );
- $linksForm.append(
- $formItem.clone().addClass('my-2')
- .append($formLabel.clone().text(settings.translations.openIn).attr("for", "openIn").addClass('col-lg-3'))
- .append($formInputSelect
- .clone().attr("id", "openIn")
- .append($("<option />", {value: '_self', text: settings.translations.sameTab}))
- .append($("<option />", {value: '_blank', text: settings.translations.newTab}))
- )
- );
- $linksForm.append( $formItem.clone().append($formButton.clone()).addClass('justify-content-center'));
- $linksDropdown.append($linksForm);
- $btnURLs.append($dropdownOuter.clone().append($linksDropdown.prepend($dropdownClose.clone())));
- /* box dropdown for video embedding */
- var $videoDropdown = $dropdownBox.clone();
- var $videoForm = $form.clone().attr("id", "richText-Video").attr("data-editor", editorID);
- $videoForm.append(
- $formItem.clone()
- .append($formLabel.clone().text(settings.translations.url).attr("for", "videoURL"))
- .append($formInput.clone().attr("id", "videoURL"))
- );
- $videoForm.append(
- $formItem.clone()
- .append($formLabel.clone().text(settings.translations.size).attr("for", "size"))
- .append(
- $formInputSelect
- .clone().attr("id", "size")
- .append($("<option />", {value: 'responsive', text: settings.translations.responsive}))
- .append($("<option />", {value: '640x360', text: '640x360'}))
- .append($("<option />", {value: '560x315', text: '560x315'}))
- .append($("<option />", {value: '480x270', text: '480x270'}))
- .append($("<option />", {value: '320x180', text: '320x180'}))
- )
- );
- $videoForm.append( $formItem.clone().append($formButton.clone()) );
- $videoDropdown.append($videoForm);
- $btnVideoEmbed.append($dropdownOuter.clone().append($videoDropdown.prepend($dropdownClose.clone())));
- /* box dropdown for image upload/image selection */
- var $imageDropdown = $dropdownBox.clone();
- var $imageForm = $form.clone().attr("id", "richText-Image").attr("data-editor", editorID);
- if(settings.imageHTML
- && ($(settings.imageHTML).find('#imageURL').length > 0 || $(settings.imageHTML).attr("id") === "imageURL")) {
- // custom image form
- $imageForm.html(settings.imageHTML);
- } else {
- // default image form
- $imageForm.append(
- $formItem.clone()
- .append($formLabel.clone().text(settings.translations.imageURL).attr("for", "imageURL"))
- .append($formInput.clone().attr("id", "imageURL"))
- );
- $imageForm.append(
- $formItem.clone()
- .append($formLabel.clone().text(settings.translations.align).attr("for", "align"))
- .append(
- $formInputSelect
- .clone().attr("id", "align")
- .append($("<option />", {value: 'left', text: settings.translations.left}))
- .append($("<option />", {value: 'center', text: settings.translations.center}))
- .append($("<option />", {value: 'right', text: settings.translations.right}))
- )
- );
- }
- $imageForm.append( $formItem.clone().append($formButton.clone()) );
- $imageDropdown.append($imageForm);
- $btnImageUpload.append($dropdownOuter.clone().append($imageDropdown.prepend($dropdownClose.clone())));
- /* box dropdown for file upload/file selection */
- var $fileDropdown = $dropdownBox.clone();
- var $fileForm = $form.clone().attr("id", "richText-File").attr("data-editor", editorID);
- if(settings.fileHTML
- && ($(settings.fileHTML).find('#fileURL').length > 0 || $(settings.fileHTML).attr("id") === "fileURL")) {
- // custom file form
- $fileForm.html(settings.fileHTML);
- } else {
- // default file form
- $fileForm.append(
- $formItem.clone()
- .append($formLabel.clone().text(settings.translations.fileURL).attr("for", "fileURL"))
- .append($formInput.clone().attr("id", "fileURL"))
- );
- $fileForm.append(
- $formItem.clone()
- .append($formLabel.clone().text(settings.translations.linkText).attr("for", "fileText"))
- .append($formInput.clone().attr("id", "fileText"))
- );
- }
- $fileForm.append( $formItem.clone().append($formButton.clone()) );
- $fileDropdown.append($fileForm);
- $btnFileUpload.append($dropdownOuter.clone().append($fileDropdown.prepend($dropdownClose.clone())));
- /* box dropdown for tables */
- var $tableDropdown = $dropdownBox.clone();
- var $tableForm = $form.clone().attr("id", "richText-Table").attr("data-editor", editorID);
- $tableForm.append(
- $formItem.clone()
- .append($formLabel.clone().text(settings.translations.rows).attr("for", "tableRows"))
- .append($formInput.clone().attr("id", "tableRows").attr("type", "number"))
- );
- $tableForm.append(
- $formItem.clone()
- .append($formLabel.clone().text(settings.translations.columns).attr("for", "tableColumns"))
- .append($formInput.clone().attr("id", "tableColumns").attr("type", "number"))
- );
- $tableForm.append( $formItem.clone().append($formButton.clone()) );
- $tableDropdown.append($tableForm);
- $btnTable.append($dropdownOuter.clone().append($tableDropdown.prepend($dropdownClose.clone())));
- /* initizalize editor */
- function init() {
- var value, attributes, attributes_html = '';
- if(settings.useParagraph !== false) {
- // set default tag when pressing ENTER to <p> instead of <div>
- document.execCommand("DefaultParagraphSeparator", false, 'p');
- }
- // reformat $inputElement to textarea
- if($inputElement.prop("tagName") === "TEXTAREA") {
- // everything perfect
- } else if($inputElement.val()) {
- value = $inputElement.val();
- attributes = $inputElement.prop("attributes");
- // loop through <select> attributes and apply them on <div>
- $.each(attributes, function() {
- if(this.name) {
- attributes_html += ' ' + this.name + '="' + this.value + '"';
- }
- });
- $inputElement.replaceWith($('<textarea' + attributes_html + ' data-richtext="init">' + value + '</textarea>'));
- $inputElement = $('[data-richtext="init"]');
- $inputElement.removeAttr("data-richtext");
- } else if($inputElement.html()) {
- value = $inputElement.html();
- attributes = $inputElement.prop("attributes");
- // loop through <select> attributes and apply them on <div>
- $.each(attributes, function() {
- if(this.name) {
- attributes_html += ' ' + this.name + '="' + this.value + '"';
- }
- });
- $inputElement.replaceWith($('<textarea' + attributes_html + ' data-richtext="init">' + value + '</textarea>'));
- $inputElement = $('[data-richtext="init"]');
- $inputElement.removeAttr("data-richtext");
- } else {
- attributes = $inputElement.prop("attributes");
- // loop through <select> attributes and apply them on <div>
- $.each(attributes, function() {
- if(this.name) {
- attributes_html += ' ' + this.name + '="' + this.value + '"';
- }
- });
- $inputElement.replaceWith($('<textarea' + attributes_html + ' data-richtext="init"></textarea>'));
- $inputElement = $('[data-richtext="init"]');
- $inputElement.removeAttr("data-richtext");
- }
- $editor = $('<div />', {class: "richText"});
- var $toolbar = $('<div />', {class: "richText-toolbar"});
- //var $editorView = $('<div />', {class: "richText-editor", id: editorID, contenteditable: true, name: settings.id});
- var $editorView = $('<div />', {class: "richText-editor", id: editorID, contenteditable: true});
- $toolbar.append($toolbarList);
-
- $toolbarList.append($toolbarElement.clone().append($btnUndo));
- $toolbarList.append($toolbarElement.clone().append($btnRedo));
- /* text formatting */
- if(settings.bold === true) {
- $toolbarList.append($toolbarElement.clone().append($btnBold));
- }
- if(settings.italic === true) {
- $toolbarList.append($toolbarElement.clone().append($btnItalic));
- }
- if(settings.underline === true) {
- $toolbarList.append($toolbarElement.clone().append($btnUnderline));
- }
- /* align */
- if(settings.leftAlign === true) {
- $toolbarList.append($toolbarElement.clone().append($btnLeftAlign));
- }
- if(settings.centerAlign === true) {
- $toolbarList.append($toolbarElement.clone().append($btnCenterAlign));
- }
- if(settings.rightAlign === true) {
- $toolbarList.append($toolbarElement.clone().append($btnRightAlign));
- }
- if(settings.justify === true) {
- $toolbarList.append($toolbarElement.clone().append($btnJustify));
- }
- /* lists */
- if(settings.ol === true) {
- $toolbarList.append($toolbarElement.clone().append($btnOL));
- }
- if(settings.ul === true) {
- $toolbarList.append($toolbarElement.clone().append($btnUL));
- }
- /* fonts */
- if(settings.fonts === true && settings.fontList.length > 0) {
- $toolbarList.append($toolbarElement.clone().append($btnFont));
- }
- if(settings.fontSize === true) {
- $toolbarList.append($toolbarElement.clone().append($btnFontSize));
- }
- /* heading */
- if(settings.heading === true) {
- $toolbarList.append($toolbarElement.clone().append($btnHeading));
- }
- /* colors */
- if(settings.fontColor === true) {
- $toolbarList.append($toolbarElement.clone().append($btnFontColor));
- }
- /* uploads */
- if(settings.imageUpload === true) {
- $toolbarList.append($toolbarElement.clone().append($btnImageUpload));
- }
- if(settings.fileUpload === true) {
- $toolbarList.append($toolbarElement.clone().append($btnFileUpload));
- }
- /* media */
- if(settings.videoEmbed === true) {
- $toolbarList.append($toolbarElement.clone().append($btnVideoEmbed));
- }
- /* urls */
- if(settings.urls === true) {
- $toolbarList.append($toolbarElement.clone().append($btnURLs));
- }
- if(settings.table === true) {
- $toolbarList.append($toolbarElement.clone().append($btnTable));
- }
- /* code */
- if(settings.removeStyles === true) {
- $toolbarList.append($toolbarElement.clone().append($btnRemoveStyles));
- }
- if(settings.code === true) {
- $toolbarList.append($toolbarElement.clone().append($btnCode));
- }
- // set current textarea value to editor
- $editorView.html($inputElement.val());
- $editor.append($toolbar);
- $editor.append($editorView);
- $editor.append($inputElement.clone().hide());
- $inputElement.replaceWith($editor);
- // append bottom toolbar
- /*$editor.append(
- $('<div />', {class: 'richText-toolbar'})
- .append($('<a />', {class: 'richText-undo is-disabled', html: '<span class="fa fa-undo"></span>', 'title': settings.translations.undo}))
- .append($('<a />', {class: 'richText-redo is-disabled', html: '<span class="fa fa-repeat fa-redo"></span>', 'title': settings.translations.redo}))
- .append($('<a />', {class: 'richText-help', html: '<span class="fa fa-question-circle"></span>'}))
- );*/
- if(settings.height && settings.height > 0) {
- // set custom editor height
- $editor.children(".richText-editor, .richText-initial").css({'min-height' : settings.height + 'px', 'height' : settings.height + 'px'});
- } else if(settings.heightPercentage && settings.heightPercentage > 0) {
- // set custom editor height in percentage
- var parentHeight = $editor.parent().innerHeight(); // get editor parent height
- var height = (settings.heightPercentage/100) * parentHeight; // calculate pixel value from percentage
- height -= $toolbar.outerHeight()*2; // remove toolbar size
- height -= parseInt($editor.css("margin-top")); // remove margins
- height -= parseInt($editor.css("margin-bottom")); // remove margins
- height -= parseInt($editor.find(".richText-editor").css("padding-top")); // remove paddings
- height -= parseInt($editor.find(".richText-editor").css("padding-bottom")); // remove paddings
- $editor.children(".richText-editor, .richText-initial").css({'min-height' : height + 'px', 'height' : height + 'px'});
- }
- // add custom class
- if(settings.class) {
- $editor.addClass(settings.class);
- }
- if(settings.id) {
- $editor.attr("id", settings.id);
- }
- // fix the first line
- fixFirstLine();
- // save history
- history[editorID].push($editor.find("textarea").val());
- }
- // initialize editor
- init();
- /** EVENT HANDLERS */
- // Help popup
- $editor.find(".richText-help").on("click", function() {
- var $editor = $(this).parents(".richText");
- if($editor) {
- var $outer = $('<div />', {class: 'richText-help-popup', style: 'position:absolute;top:0;right:0;bottom:0;left:0;background-color: rgba(0,0,0,0.3);'});
- var $inner = $('<div />', {style: 'position:relative;margin:60px auto;padding:20px;background-color:#FAFAFA;width:70%;font-family:Calibri,Verdana,Helvetica,sans-serif;font-size:small;'});
- var $content = $('<div />', {html: '<span id="closeHelp" style="display:block;position:absolute;top:0;right:0;padding:10px;cursor:pointer;" title="' + settings.translations.close + '"><span class="fa fa-times"></span></span>'});
- $content.append('<h3 style="margin:0;">RichText</h3>');
- $content.append('<hr><br>Powered by <a href="https://github.com/webfashionist/RichText" target="_blank">webfashionist/RichText</a> (Github) <br>License: <a href="https://github.com/webfashionist/RichText/blob/master/LICENSE" target="_blank">AGPL-3.0</a>');
- $outer.append($inner.append($content));
- $editor.append($outer);
- $outer.on("click", "#closeHelp", function() {
- $(this).parents('.richText-help-popup').remove();
- });
- }
- });
- // undo / redo
- $(document).on("click", ".richText-undo, .richText-redo", function(e) {
- var $this = $(this);
- var $editor = $this.parents('.richText');
- if($this.hasClass("richText-undo") && !$this.hasClass("is-disabled")) {
- undo($editor);
- } else if($this.hasClass("richText-redo") && !$this.hasClass("is-disabled")) {
- redo($editor);
- }
- });
- // Saving changes from editor to textarea
- $(document).on("input change blur keydown keyup", ".richText-editor", function(e) {
- if((e.keyCode === 9 || e.keyCode === "9") && e.type === "keydown") {
- // tab through table cells
- e.preventDefault();
- tabifyEditableTable(window, e);
- return false;
- }
- fixFirstLine();
- updateTextarea();
- doSave($(this).attr("id"));
- });
- // add context menu to several Node elements
- $(document).on('contextmenu', '.richText-editor', function(e) {
- var $list = $('<ul />', {'class': 'list-rightclick richText-list'});
- var $li = $('<li />');
- // remove Node selection
- $('.richText-editor').find('.richText-editNode').removeClass('richText-editNode');
- var $target = $(e.target);
- var $richText = $target.parents('.richText');
- var $toolbar = $richText.find('.richText-toolbar');
- var positionX = e.pageX - $richText.offset().left;
- var positionY = e.pageY - $richText.offset().top;
- $list.css({
- 'top': positionY,
- 'left': positionX
- });
- if($target.prop("tagName") === "A") {
- // edit URL
- e.preventDefault();
- $list.append($li.clone().html('<span class="fa fa-link"></span>'));
- $target.parents('.richText').append($list);
- $list.find('.fa-link').on('click', function() {
- $('.list-rightclick.richText-list').remove();
- $target.addClass('richText-editNode');
- var $popup = $toolbar.find('#richText-URL');
- $popup.find('input#url').val($target.attr('href'));
- $popup.find('input#urlText').val($target.text());
- $popup.find('select#openIn').val($target.attr('target'));
- $toolbar.find('.richText-btn').children('.fa-link').parents('li').addClass('is-selected');
- });
- return false;
- } else if($target.prop("tagName") === "IMG") {
- // edit image
- e.preventDefault();
- $list.append($li.clone().html('<span class="fa fa-image"></span>'));
- $target.parents('.richText').append($list);
- $list.find('.fa-image').on('click', function() {
- var align;
- if($target.parent('div').length > 0 && $target.parent('div').attr('style') === 'text-align:center;') {
- align = 'center';
- } else {
- align = $target.attr('align');
- }
- $('.list-rightclick.richText-list').remove();
- $target.addClass('richText-editNode');
- var $popup = $toolbar.find('#richText-Image');
- $popup.find('input#imageURL').val($target.attr('src'));
- $popup.find('select#align').val(align);
- $toolbar.find('.richText-btn').children('.fa-image').parents('li').addClass('is-selected');
- });
- return false;
- }
- });
- // Saving changes from textarea to editor
- $(document).on("input change blur", ".richText-initial", function() {
- if(settings.useSingleQuotes === true) {
- $(this).val(changeAttributeQuotes($(this).val()));
- }
- var editorID = $(this).siblings('.richText-editor').attr("id");
- updateEditor(editorID);
- doSave(editorID);
- });
- // Save selection seperately (mainly needed for Safari)
- $(document).on("dblclick mouseup", ".richText-editor", function() {
- var editorID = $(this).attr("id");
- doSave(editorID);
- });
- // embedding video
- $(document).on("click", "#richText-Video button.btn", function(event) {
- event.preventDefault();
- var $button = $(this);
- var $form = $button.parent('.richText-form-item').parent('.richText-form');
- if($form.attr("data-editor") === editorID) {
- // only for the currently selected editor
- var url = $form.find('input#videoURL').val();
- var size = $form.find('select#size').val();
- if(!url) {
- // no url set
- $form.prepend($('<div />', {style: 'color:red;display:none;', class: 'form-item is-error', text: settings.translations.pleaseEnterURL}));
- $form.children('.form-item.is-error').slideDown();
- setTimeout(function() {
- $form.children('.form-item.is-error').slideUp(function () {
- $(this).remove();
- });
- }, 5000);
- } else {
- // write html in editor
- var html = '';
- html = getVideoCode(url, size);
- if(!html) {
- $form.prepend($('<div />', {style: 'color:red;display:none;', class: 'form-item is-error', text: settings.translations.videoURLnotSupported}));
- $form.children('.form-item.is-error').slideDown();
- setTimeout(function() {
- $form.children('.form-item.is-error').slideUp(function () {
- $(this).remove();
- });
- }, 5000);
- } else {
- if(settings.useSingleQuotes === true) {
- } else {
- }
- restoreSelection(editorID, true);
- pasteHTMLAtCaret(html);
- updateTextarea();
- // reset input values
- $form.find('input#videoURL').val('');
- $('.richText-toolbar li.is-selected').removeClass("is-selected");
- }
- }
- }
- });
- // Resize images
- $(document).on('mousedown', function(e) {
- var $target = $(e.target);
- if(!$target.hasClass('richText-list') && $target.parents('.richText-list').length === 0) {
- // remove context menu
- $('.richText-list.list-rightclick').remove();
- if(!$target.hasClass('richText-form') && $target.parents('.richText-form').length === 0) {
- $('.richText-editNode').each(function () {
- var $this = $(this);
- $this.removeClass('richText-editNode');
- if ($this.attr('class') === '') {
- $this.removeAttr('class');
- }
- });
- }
- }
- if($target.prop("tagName") === "IMG" && $target.parents("#" + editorID)) {
- startX = e.pageX;
- startY = e.pageY;
- startW = $target.innerWidth();
- startH = $target.innerHeight();
- var left = $target.offset().left;
- var right = $target.offset().left + $target.innerWidth();
- var bottom = $target.offset().top + $target.innerHeight();
- var top = $target.offset().top;
- var resize = false;
- $target.css({'cursor' : 'default'});
- if(startY <= bottom && startY >= bottom-20 && startX >= right-20 && startX <= right) {
- // bottom right corner
- $resizeImage = $target;
- $resizeImage.css({'cursor' : 'nwse-resize'});
- resize = true;
- }
- if((resize === true || $resizeImage) && !$resizeImage.data("width")) {
- // set initial image size and prevent dragging image while resizing
- $resizeImage.data("width", $target.parents("#" + editorID).innerWidth());
- $resizeImage.data("height", $target.parents("#" + editorID).innerHeight()*3);
- e.preventDefault();
- } else if(resize === true || $resizeImage) {
- // resizing active, prevent other events
- e.preventDefault();
- } else {
- // resizing disabled, allow dragging image
- $resizeImage = null;
- }
-
- }
- });
- $(document)
- .mouseup(function(){
- if($resizeImage) {
- $resizeImage.css({'cursor' : 'default'});
- }
- $resizeImage = null;
- })
- .mousemove(function(e){
- if($resizeImage!==null){
- var maxWidth = $resizeImage.data('width');
- var currentWidth = $resizeImage.width();
- var maxHeight = $resizeImage.data('height');
- var currentHeight = $resizeImage.height();
- if((startW + e.pageX-startX) <= maxWidth && (startH + e.pageY-startY) <= maxHeight) {
- // only resize if new size is smaller than the original image size
- $resizeImage.innerWidth (startW + e.pageX-startX); // only resize width to adapt height proportionally
- // $box.innerHeight(startH + e.pageY-startY);
- updateTextarea();
- } else if((startW + e.pageX-startX) <= currentWidth && (startH + e.pageY-startY) <= currentHeight) {
- // only resize if new size is smaller than the previous size
- $resizeImage.innerWidth (startW + e.pageX-startX); // only resize width to adapt height proportionally
- updateTextarea();
- }
- }
- });
- // adding URL
- $(document).on("click", "#richText-URL button.btn", function(event) {
- event.preventDefault();
- var $button = $(this);
- var $form = $button.parent('.richText-form-item').parent('.richText-form');
- if($form.attr("data-editor") === editorID) {
- // only for currently selected editor
- var url = $form.find('input#url').val();
- var text = $form.find('input#urlText').val();
- var target = $form.find('#openIn').val();
- // set default values
- if(!target) {
- target = '_self';
- }
- if(!text) {
- text = url;
- }
- if(!url) {
- // no url set
- $form.prepend($('<div />', {style: 'color:red;display:none;', class: 'form-item is-error', text: settings.translations.pleaseEnterURL}));
- $form.children('.form-item.is-error').slideDown();
- setTimeout(function() {
- $form.children('.form-item.is-error').slideUp(function () {
- $(this).remove();
- });
- }, 5000);
- } else {
- // write html in editor
- var html = '';
- if(settings.useSingleQuotes === true) {
- html = "<a href='" + url + "' target='" + target + "'>" + text + "</a>";
- } else {
- html = '<a href="' + url + '" target="' + target + '">' + text + '</a>';
- }
- restoreSelection(editorID, false, true);
- var $editNode = $('.richText-editNode');
- if($editNode.length > 0 && $editNode.prop("tagName") === "A") {
- $editNode.attr("href", url);
- $editNode.attr("target", target);
- $editNode.text(text);
- $editNode.removeClass('richText-editNode');
- if($editNode.attr('class') === '') {
- $editNode.removeAttr('class');
- }
- } else {
- pasteHTMLAtCaret(html);
- }
- // reset input values
- $form.find('input#url').val('');
- $form.find('input#urlText').val('');
- $('.richText-toolbar li.is-selected').removeClass("is-selected");
- }
- }
- });
- // adding image
- $(document).on("click", "#richText-Image button.btn", function(event) {
- event.preventDefault();
- var $button = $(this);
- var $form = $button.parent('.richText-form-item').parent('.richText-form');
- if($form.attr("data-editor") === editorID) {
- // only for currently selected editor
- var url = $form.find('#imageURL').val();
- var align = $form.find('select#align').val();
- // set default values
- if(!align) {
- align = 'center';
- }
- if(!url) {
- // no url set
- $form.prepend($('<div />', {style: 'color:red;display:none;', class: 'form-item is-error', text: settings.translations.pleaseSelectImage}));
- $form.children('.form-item.is-error').slideDown();
- setTimeout(function() {
- $form.children('.form-item.is-error').slideUp(function () {
- $(this).remove();
- });
- }, 5000);
- } else {
- // write html in editor
- var html = '';
- if(settings.useSingleQuotes === true) {
- if(align === "center") {
- html = "<div style='text-align:center;'><img src='" + url + "'></div>";
- } else {
- html = "<img src='" + url + "' align='" + align + "'>";
- }
- } else {
- if(align === "center") {
- html = '<div style="text-align:center;"><img src="' + url + '"></div>';
- } else {
- html = '<img src="' + url + '" align="' + align + '">';
- }
- }
- restoreSelection(editorID, true);
- var $editNode = $('.richText-editNode');
- if($editNode.length > 0 && $editNode.prop("tagName") === "IMG") {
- $editNode.attr("src", url);
- if($editNode.parent('div').length > 0 && $editNode.parent('div').attr('style') === 'text-align:center;' && align !== 'center') {
- $editNode.unwrap('div');
- $editNode.attr('align', align);
- } else if(($editNode.parent('div').length === 0 || $editNode.parent('div').attr('style') !== 'text-align:center;') && align === 'center' ) {
- $editNode.wrap('<div style="text-align:center;"></div>');
- $editNode.removeAttr('align');
- } else {
- $editNode.attr('align', align);
- }
- $editNode.removeClass('richText-editNode');
- if($editNode.attr('class') === '') {
- $editNode.removeAttr('class');
- }
- } else {
- pasteHTMLAtCaret(html);
- }
- // reset input values
- $form.find('input#imageURL').val('');
- $('.richText-toolbar li.is-selected').removeClass("is-selected");
- }
- }
- });
- // adding file
- $(document).on("click", "#richText-File button.btn", function(event) {
- event.preventDefault();
- var $button = $(this);
- var $form = $button.parent('.richText-form-item').parent('.richText-form');
- if($form.attr("data-editor") === editorID) {
- // only for currently selected editor
- var url = $form.find('#fileURL').val();
- var text = $form.find('#fileText').val();
- // set default values
- if(!text) {
- text = url;
- }
- if(!url) {
- // no url set
- $form.prepend($('<div />', {style: 'color:red;display:none;', class: 'form-item is-error', text: settings.translations.pleaseSelectFile}));
- $form.children('.form-item.is-error').slideDown();
- setTimeout(function() {
- $form.children('.form-item.is-error').slideUp(function () {
- $(this).remove();
- });
- }, 5000);
- } else {
- // write html in editor
- var html = '';
- if(settings.useSingleQuotes === true) {
- html = "<a href='" + url + "' target='_blank'>" + text + "</a>";
- } else {
- html = '<a href="' + url + '" target="_blank">' + text + '</a>';
- }
- restoreSelection(editorID, true);
- pasteHTMLAtCaret(html);
- // reset input values
- $form.find('input#fileURL').val('');
- $form.find('input#fileText').val('');
- $('.richText-toolbar li.is-selected').removeClass("is-selected");
- }
- }
- });
- // adding table
- $(document).on("click", "#richText-Table button.btn", function(event) {
- event.preventDefault();
- var $button = $(this);
- var $form = $button.parent('.richText-form-item').parent('.richText-form');
- if($form.attr("data-editor") === editorID) {
- // only for currently selected editor
- var rows = $form.find('input#tableRows').val();
- var columns = $form.find('input#tableColumns').val();
- // set default values
- if(!rows || rows <= 0) {
- rows = 2;
- }
- if(!columns || columns <= 0) {
- columns = 2;
- }
-
- // generate table
- var html = '';
- if(settings.useSingleQuotes === true) {
- html = "<table class='table-1'><tbody>";
- } else {
- html = '<table class="table-1"><tbody>';
- }
- for(var i = 1; i <= rows; i++) {
- // start new row
- html += '<tr>';
- for(var n = 1; n <= columns; n++) {
- // start new column in row
- html += '<td> </td>';
- }
- html += '</tr>';
- }
- html += '</tbody></table>';
- // write html in editor
- restoreSelection(editorID, true);
- pasteHTMLAtCaret(html);
- // reset input values
- $form.find('input#tableColumns').val('');
- $form.find('input#tableRows').val('');
- $('.richText-toolbar li.is-selected').removeClass("is-selected");
- }
- });
- // opening / closing toolbar dropdown
- $(document).on("click", function(event) {
- var $clickedElement = $(event.target);
- if($clickedElement.parents('.richText-toolbar').length === 0) {
- // element not in toolbar
- // ignore
- } else if($clickedElement.hasClass("richText-dropdown-outer")) {
- // closing dropdown by clicking inside the editor
- $clickedElement.parent('a').parent('li').removeClass("is-selected");
- } else if($clickedElement.find(".richText").length > 0) {
- // closing dropdown by clicking outside of the editor
- $('.richText-toolbar li').removeClass("is-selected");
- } else if($clickedElement.parent().hasClass("richText-dropdown-close")) {
- // closing dropdown by clicking on the close button
- $('.richText-toolbar li').removeClass("is-selected");
- } else if($clickedElement.hasClass("richText-btn") && $(event.target).children('.richText-dropdown-outer').length > 0) {
- // opening dropdown by clicking on toolbar button
- $clickedElement.parent('li').addClass("is-selected");
- if($clickedElement.children('.fa,svg').hasClass("fa-link")) {
- // put currently selected text in URL form to replace it
- restoreSelection(editorID, false, true);
- var selectedText = getSelectedText();
- $clickedElement.find("input#urlText").val('');
- $clickedElement.find("input#url").val('');
- if(selectedText) {
- $clickedElement.find("input#urlText").val(selectedText);
- }
- } else if($clickedElement.hasClass("fa-image")) {
- // image
- }
- }
- });
- // Executing editor commands
- $(document).on("click", ".richText-toolbar a[data-command]", function(event) {
- var $button = $(this);
- var $toolbar = $button.closest('.richText-toolbar');
- var $editor = $toolbar.siblings('.richText-editor');
- var id = $editor.attr("id");
- if($editor.length > 0 && id === editorID && (!$button.parent("li").attr('data-disable') || $button.parent("li").attr('data-disable') === "false")) {
- event.preventDefault();
- var command = $(this).data("command");
- if(command === "toggleCode") {
- toggleCode($editor.attr("id"));
- } else {
- var option = null;
- if ($(this).data('option')) {
- option = $(this).data('option').toString();
- if (option.match(/^h[1-6]$/)) {
- command = "heading";
- }
- }
- formatText(command, option, id);
- if (command === "removeFormat") {
- // remove HTML/CSS formatting
- $editor.find('*').each(function() {
- // remove all, but very few, attributes from the nodes
- var keepAttributes = [
- "id", "class",
- "name", "action", "method",
- "src", "align", "alt", "title",
- "style", "webkitallowfullscreen", "mozallowfullscreen", "allowfullscreen",
- "width", "height", "frameborder"
- ];
- var element = $(this);
- var attributes = $.map(this.attributes, function(item) {
- return item.name;
- });
- $.each(attributes, function(i, item) {
- if(keepAttributes.indexOf(item) < 0 && item.substr(0, 5) !== 'data-') {
- element.removeAttr(item);
- }
- });
- if(element.prop('tagName') === "A") {
- // remove empty URL tags
- element.replaceWith(function() {
- return $('<span />', {html: $(this).html()});
- });
- }
- });
- formatText('formatBlock', 'div', id);
- }
- // clean up empty tags, which can be created while replacing formatting or when copy-pasting from other tools
- $editor.find('div:empty,p:empty,li:empty,h1:empty,h2:empty,h3:empty,h4:empty,h5:empty,h6:empty').remove();
- $editor.find('h1,h2,h3,h4,h5,h6').unwrap('h1,h2,h3,h4,h5,h6');
- }
- }
- // close dropdown after click
- $button.parents('li.is-selected').removeClass('is-selected');
- });
- /** INTERNAL METHODS **/
- /**
- * Format text in editor
- * @param {string} command
- * @param {string|null} option
- * @param {string} editorID
- * @private
- */
- function formatText(command, option, editorID) {
- if (typeof option === "undefined") {
- option = null;
- }
- // restore selection from before clicking on any button
- doRestore(editorID);
- // Temporarily enable designMode so that
- // document.execCommand() will work
- // document.designMode = "ON";
- // Execute the command
- if(command === "heading" && getSelectedText()) {
- // IE workaround
- pasteHTMLAtCaret('<' + option + '>' + getSelectedText() + '</' + option + '>');
- } else if(command === "fontSize" && parseInt(option) > 0) {
- var selection = getSelectedText();
- selection = (selection + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '<br>' + '$2');
- var html = (settings.useSingleQuotes ? "<span style='font-size:" + option + "px;'>" + selection + "</span>" : '<span style="font-size:' + option + 'px;">' + selection + '</span>');
- pasteHTMLAtCaret(html);
- } else {
- document.execCommand(command, false, option);
- }
- // Disable designMode
- // document.designMode = "OFF";
- }
- /**
- * Update textarea when updating editor
- * @private
- */
- function updateTextarea() {
- var $editor = $('#' + editorID);
- var content = $editor.html();
- if(settings.useSingleQuotes === true) {
- content = changeAttributeQuotes(content);
- }
- $editor.siblings('.richText-initial').val(content);
- }
- /**
- * Update editor when updating textarea
- * @private
- */
- function updateEditor(editorID) {
- var $editor = $('#' + editorID);
- var content = $editor.siblings('.richText-initial').val();
- $editor.html(content);
- }
- /**
- * Save caret position and selection
- * @return object
- **/
- function saveSelection(editorID) {
- var containerEl = document.getElementById(editorID);
- var range, start, end, type;
- if(window.getSelection && document.createRange) {
- var sel = window.getSelection && window.getSelection();
- if (sel && sel.rangeCount > 0 && $(sel.anchorNode).parents('#' + editorID).length > 0) {
- range = window.getSelection().getRangeAt(0);
- var preSelectionRange = range.cloneRange();
- preSelectionRange.selectNodeContents(containerEl);
- preSelectionRange.setEnd(range.startContainer, range.startOffset);
-
- start = preSelectionRange.toString().length;
- end = (start + range.toString().length);
- type = (start === end ? 'caret' : 'selection');
- anchor = sel.anchorNode; //(type === "caret" && sel.anchorNode.tagName ? sel.anchorNode : false);
- start = (type === 'caret' && anchor !== false ? 0 : preSelectionRange.toString().length);
- end = (type === 'caret' && anchor !== false ? 0 : (start + range.toString().length));
- return {
- start: start,
- end: end,
- type: type,
- anchor: anchor,
- editorID: editorID
- }
- }
- }
- return (savedSelection ? savedSelection : {
- start: 0,
- end: 0
- });
- }
- /**
- * Restore selection
- **/
- function restoreSelection(editorID, media, url) {
- var containerEl = document.getElementById(editorID);
- var savedSel = savedSelection;
- if(!savedSel) {
- // fix selection if editor has not been focused
- savedSel = {
- 'start': 0,
- 'end': 0,
- 'type': 'caret',
- 'editorID': editorID,
- 'anchor': $('#' + editorID).children('div')[0]
- };
- }
- if(savedSel.editorID !== editorID) {
- return false;
- } else if(media === true) {
- containerEl = (savedSel.anchor ? savedSel.anchor : containerEl); // fix selection issue
- } else if(url === true) {
- if(savedSel.start === 0 && savedSel.end === 0) {
- containerEl = (savedSel.anchor ? savedSel.anchor : containerEl); // fix selection issue
- }
- }
- if (window.getSelection && document.createRange) {
- var charIndex = 0, range = document.createRange();
- if(!range || !containerEl) { window.getSelection().removeAllRanges(); return true; }
- range.setStart(containerEl, 0);
- range.collapse(true);
- var nodeStack = [containerEl], node, foundStart = false, stop = false;
- while (!stop && (node = nodeStack.pop())) {
- if (node.nodeType === 3) {
- var nextCharIndex = charIndex + node.length;
- if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) {
- range.setStart(node, savedSel.start - charIndex);
- foundStart = true;
- }
- if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) {
- range.setEnd(node, savedSel.end - charIndex);
- stop = true;
- }
- charIndex = nextCharIndex;
- } else {
- var i = node.childNodes.length;
- while (i--) {
- nodeStack.push(node.childNodes[i]);
- }
- }
- }
- var sel = window.getSelection();
- sel.removeAllRanges();
- sel.addRange(range);
- }
- }
- /**
- * Save caret position and selection
- * @return object
- **/
- /*
- function saveSelection(editorID) {
- var containerEl = document.getElementById(editorID);
- var start;
- if (window.getSelection && document.createRange) {
- var sel = window.getSelection && window.getSelection();
- if (sel && sel.rangeCount > 0) {
- var range = window.getSelection().getRangeAt(0);
- var preSelectionRange = range.cloneRange();
- preSelectionRange.selectNodeContents(containerEl);
- preSelectionRange.setEnd(range.startContainer, range.startOffset);
- start = preSelectionRange.toString().length;
- return {
- start: start,
- end: start + range.toString().length,
- editorID: editorID
- }
- } else {
- return (savedSelection ? savedSelection : {
- start: 0,
- end: 0
- });
- }
- } else if (document.selection && document.body.createTextRange) {
- var selectedTextRange = document.selection.createRange();
- var preSelectionTextRange = document.body.createTextRange();
- preSelectionTextRange.moveToElementText(containerEl);
- preSelectionTextRange.setEndPoint("EndToStart", selectedTextRange);
- start = preSelectionTextRange.text.length;
- return {
- start: start,
- end: start + selectedTextRange.text.length,
- editorID: editorID
- };
- }
- }
- */
- /**
- * Restore selection
- **/
- /*
- function restoreSelection(editorID) {
- var containerEl = document.getElementById(editorID);
- var savedSel = savedSelection;
- if(savedSel.editorID !== editorID) {
- return false;
- }
- if (window.getSelection && document.createRange) {
- var charIndex = 0, range = document.createRange();
- range.setStart(containerEl, 0);
- range.collapse(true);
- var nodeStack = [containerEl], node, foundStart = false, stop = false;
- while (!stop && (node = nodeStack.pop())) {
- if (node.nodeType === 3) {
- var nextCharIndex = charIndex + node.length;
- if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) {
- range.setStart(node, savedSel.start - charIndex);
- foundStart = true;
- }
- if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) {
- range.setEnd(node, savedSel.end - charIndex);
- stop = true;
- }
- charIndex = nextCharIndex;
- } else {
- var i = node.childNodes.length;
- while (i--) {
- nodeStack.push(node.childNodes[i]);
- }
- }
- }
- var sel = window.getSelection();
- sel.removeAllRanges();
- sel.addRange(range);
- } else if (document.selection && document.body.createTextRange) {
- var textRange = document.body.createTextRange();
- textRange.moveToElementText(containerEl);
- textRange.collapse(true);
- textRange.moveEnd("character", savedSel.end);
- textRange.moveStart("character", savedSel.start);
- textRange.select();
- }
- }
- */
- /**
- * Enables tabbing/shift-tabbing between contentEditable table cells
- * @param {Window} win - Active window context.
- * @param {Event} e - jQuery Event object for the keydown that fired.
- */
- function tabifyEditableTable(win, e) {
- if (e.keyCode !== 9) {
- return false;
- }
- var sel;
- if (win.getSelection) {
- sel = win.getSelection();
- if (sel.rangeCount > 0) {
- var textNode = null,
- direction = null;
- if (!e.shiftKey) {
- direction = "next";
- textNode = (sel.focusNode.nodeName === "TD")
- ? (sel.focusNode.nextSibling != null)
- ? sel.focusNode.nextSibling
- : (sel.focusNode.parentNode.nextSibling != null)
- ? sel.focusNode.parentNode.nextSibling.childNodes[0]
- : null
- : (sel.focusNode.parentNode.nextSibling != null)
- ? sel.focusNode.parentNode.nextSibling
- : (sel.focusNode.parentNode.parentNode.nextSibling != null)
- ? sel.focusNode.parentNode.parentNode.nextSibling.childNodes[0]
- : null;
- } else {
- direction = "previous";
- textNode = (sel.focusNode.nodeName === "TD")
- ? (sel.focusNode.previousSibling != null)
- ? sel.focusNode.previousSibling
- : (sel.focusNode.parentNode.previousSibling != null)
- ? sel.focusNode.parentNode.previousSibling.childNodes[sel.focusNode.parentNode.previousSibling.childNodes.length - 1]
- : null
- : (sel.focusNode.parentNode.previousSibling != null)
- ? sel.focusNode.parentNode.previousSibling
- : (sel.focusNode.parentNode.parentNode.previousSibling != null)
- ? sel.focusNode.parentNode.parentNode.previousSibling.childNodes[sel.focusNode.parentNode.parentNode.previousSibling.childNodes.length - 1]
- : null;
- }
- if (textNode != null) {
- sel.collapse(textNode, Math.min(textNode.length, sel.focusOffset + 1));
- if (textNode.textContent != null) {
- sel.selectAllChildren(textNode);
- }
- e.preventDefault();
- return true;
- } else if(textNode === null && direction === "next" && sel.focusNode.nodeName === "TD") {
- // add new row on TAB if arrived at the end of the row
- var $table = $(sel.focusNode).parents("table");
- var cellsPerLine = $table.find("tr").first().children("td").length;
- var $tr = $("<tr />");
- var $td = $("<td />");
- for(var i = 1; i <= cellsPerLine; i++) {
- $tr.append($td.clone());
- }
- $table.append($tr);
- // simulate tabing through table
- tabifyEditableTable(window, {keyCode: 9, shiftKey: false, preventDefault: function(){}});
- }
- }
- }
- return false;
- }
- /**
- * Returns the text from the current selection
- * @private
- * @return {string|boolean}
- */
- function getSelectedText() {
- var range;
- if (window.getSelection) { // all browsers, except IE before version 9
- range = window.getSelection();
- return range.toString() ? range.toString() : range.focusNode.nodeValue;
- } else if (document.selection.createRange) { // Internet Explorer
- range = document.selection.createRange();
- return range.text;
- }
- return false;
- }
- /**
- * Save selection
- */
- function doSave(editorID) {
- var $textarea = $('.richText-editor#' + editorID).siblings('.richText-initial');
- addHistory($textarea.val(), editorID);
- savedSelection = saveSelection(editorID);
- }
- /**
- * Add to history
- * @param val Editor content
- * @param id Editor ID
- */
- function addHistory(val, id) {
- if(!history[id]) {
- return false;
- }
- if(history[id].length-1 > historyPosition[id]) {
- history[id].length = historyPosition[id] + 1;
- }
- if(history[id][history[id].length-1] !== val) {
- history[id].push(val);
- }
- historyPosition[id] = history[id].length-1;
- setHistoryButtons(id);
- }
- function setHistoryButtons(id) {
- if(historyPosition[id] <= 0) {
- $editor.find(".richText-undo").addClass("is-disabled");
- } else {
- $editor.find(".richText-undo").removeClass("is-disabled");
- }
- if(historyPosition[id] >= history[id].length-1 || history[id].length === 0) {
- $editor.find(".richText-redo").addClass("is-disabled");
- } else {
- $editor.find(".richText-redo").removeClass("is-disabled");
- }
- }
- /**
- * Undo
- * @param $editor
- */
- function undo($editor) {
- var id = $editor.children('.richText-editor').attr('id');
- historyPosition[id]--;
- if(!historyPosition[id] && historyPosition[id] !== 0) {
- return false;
- }
- var value = history[id][historyPosition[id]];
- $editor.find('textarea').val(value);
- $editor.find('.richText-editor').html(value);
- setHistoryButtons(id);
- }
- /**
- * Undo
- * @param $editor
- */
- function redo($editor) {
- var id = $editor.children('.richText-editor').attr('id');
- historyPosition[id]++;
- if(!historyPosition[id] && historyPosition[id] !== 0) {
- return false;
- }
- var value = history[id][historyPosition[id]];
- $editor.find('textarea').val(value);
- $editor.find('.richText-editor').html(value);
- setHistoryButtons(id);
- }
- /**
- * Restore selection
- */
- function doRestore(id) {
- if(savedSelection) {
- restoreSelection((id ? id : savedSelection.editorID));
- }
- }
- /**
- * Paste HTML at caret position
- * @param {string} html HTML code
- * @private
- */
- function pasteHTMLAtCaret(html) {
- // add HTML code for Internet Explorer
- var sel, range;
- if (window.getSelection) {
- // IE9 and non-IE
- sel = window.getSelection();
- if (sel.getRangeAt && sel.rangeCount) {
- range = sel.getRangeAt(0);
- range.deleteContents();
- // Range.createContextualFragment() would be useful here but is
- // only relatively recently standardized and is not supported in
- // some browsers (IE9, for one)
- var el = document.createElement("div");
- el.innerHTML = html;
- var frag = document.createDocumentFragment(), node, lastNode;
- while ( (node = el.firstChild) ) {
- lastNode = frag.appendChild(node);
- }
- range.insertNode(frag);
- // Preserve the selection
- if (lastNode) {
- range = range.cloneRange();
- range.setStartAfter(lastNode);
- range.collapse(true);
- sel.removeAllRanges();
- sel.addRange(range);
- }
- }
- } else if (document.selection && document.selection.type !== "Control") {
- // IE < 9
- document.selection.createRange().pasteHTML(html);
- }
- }
- /**
- * Change quotes around HTML attributes
- * @param {string} string
- * @return {string}
- */
- function changeAttributeQuotes(string) {
- if(!string) {
- return '';
- }
- var regex;
- var rstring;
- if(settings.useSingleQuotes === true) {
- regex = /\s+(\w+\s*=\s*(["][^"]*["])|(['][^']*[']))+/g;
- rstring = string.replace(regex, function($0,$1,$2){
- if(!$2) {return $0;}
- return $0.replace($2, $2.replace(/\"/g, "'"));
- });
- } else {
- regex = /\s+(\w+\s*=\s*(['][^']*['])|(["][^"]*["]))+/g;
- rstring = string.replace(regex, function($0,$1,$2){
- if(!$2) {return $0;}
- return $0.replace($2, $2.replace(/'/g, '"'));
- });
- }
- return rstring;
- }
- /**
- * Load colors for font or background
- * @param {string} command Command
- * @returns {string}
- * @private
- */
- function loadColors(command) {
- var colors = [];
- var result = '';
- colors["#FFFFFF"] = settings.translations.white;
- colors["#000000"] = settings.translations.black;
- colors["#7F6000"] = settings.translations.brown;
- colors["#938953"] = settings.translations.beige;
- colors["#1F497D"] = settings.translations.darkBlue;
- colors["blue"] = settings.translations.blue;
- colors["#4F81BD"] = settings.translations.lightBlue;
- colors["#953734"] = settings.translations.darkRed;
- colors["red"] = settings.translations.red;
- colors["#4F6128"] = settings.translations.darkGreen;
- colors["green"] = settings.translations.green;
- colors["#3F3151"] = settings.translations.purple;
- colors["#31859B"] = settings.translations.darkTurquois;
- colors["#4BACC6"] = settings.translations.turquois;
- colors["#E36C09"] = settings.translations.darkOrange;
- colors["#F79646"] = settings.translations.orange;
- colors["#FFFF00"] = settings.translations.yellow;
- if(settings.colors && settings.colors.length > 0) {
- colors = settings.colors;
- }
- for (var i in colors) {
- result += '<li class="inline"><a data-command="' + command + '" data-option="' + i + '" style="text-align:left;" title="' + colors[i] + '"><span class="box-color" style="background-color:' + i + '"></span></a></li>';
- }
- return result;
- }
- /**
- * Toggle (show/hide) code or editor
- * @private
- */
- function toggleCode(editorID) {
- doRestore(editorID);
- if($editor.find('.richText-editor').is(":visible")) {
- // show code
- $editor.find('.richText-initial').show();
- $editor.find('.richText-editor').hide();
- // disable non working buttons
- $('.richText-toolbar').find('.richText-btn').each(function() {
- if($(this).children('.fa-code').length === 0) {
- $(this).parent('li').attr("data-disable", "true");
- }
- });
- convertCaretPosition(editorID, savedSelection);
- } else {
- // show editor
- $editor.find('.richText-initial').hide();
- $editor.find('.richText-editor').show();
- convertCaretPosition(editorID, savedSelection, true);
- // enable all buttons again
- $('.richText-toolbar').find('li').removeAttr("data-disable");
- }
- }
- /**
- * Convert caret position from editor to code view (or in reverse)
- * @param {string} editorID
- * @param {object} selection
- * @param {boolean} reverse
- **/
- function convertCaretPosition(editorID, selection, reverse) {
- var $editor = $('#' + editorID);
- var $textarea = $editor.siblings(".richText-initial");
- var code = $textarea.val();
- if(!selection || !code) {
- return {start: 0, end: 0};
- }
- if(reverse === true) {
- savedSelection = {start: $editor.text().length, end: $editor.text().length, editorID: editorID};
- restoreSelection(editorID);
- return true;
- }
- selection.node = $textarea[0];
- var states = {start: false, end: false, tag: false, isTag: false, tagsCount: 0, isHighlight: (selection.start !== selection.end)};
- for(var i = 0; i < code.length; i++) {
- if(code[i] === "<") {
- // HTML tag starts
- states.isTag = true;
- states.tag = false;
- states.tagsCount++;
- } else if(states.isTag === true && code[i] !== ">") {
- states.tagsCount++;
- } else if(states.isTag === true && code[i] === ">") {
- states.isTag = false;
- states.tag = true;
- states.tagsCount++;
- } else if(states.tag === true) {
- states.tag = false;
- }
- if(!reverse) {
- if((selection.start + states.tagsCount) <= i && states.isHighlight && !states.isTag && !states.tag && !states.start) {
- selection.start = i;
- states.start = true;
- } else if((selection.start + states.tagsCount) <= i+1 && !states.isHighlight && !states.isTag && !states.tag && !states.start) {
- selection.start = i+1;
- states.start = true;
- }
- if((selection.end + states.tagsCount) <= i+1 && !states.isTag && !states.tag && !states.end) {
- selection.end = i+1;
- states.end = true;
- }
- }
- }
- createSelection(selection.node, selection.start, selection.end);
- return selection;
- }
- /**
- * Create selection on node element
- * @param {Node} field
- * @param {int} start
- * @param {int} end
- **/
- function createSelection(field, start, end) {
- if( field.createTextRange ) {
- var selRange = field.createTextRange();
- selRange.collapse(true);
- selRange.moveStart('character', start);
- selRange.moveEnd('character', end);
- selRange.select();
- field.focus();
- } else if( field.setSelectionRange ) {
- field.focus();
- field.setSelectionRange(start, end);
- } else if( typeof field.selectionStart != 'undefined' ) {
- field.selectionStart = start;
- field.selectionEnd = end;
- field.focus();
- }
- }
- /**
- * Get video embed code from URL
- * @param {string} url Video URL
- * @param {string} size Size in the form of widthxheight
- * @return {string|boolean}
- * @private
- **/
- function getVideoCode(url, size) {
- var video = getVideoID(url);
- var responsive = false, success = false;
- if(!video) {
- // video URL not supported
- return false;
- }
- if(!size) {
- size = "640x360";
- size = size.split("x");
- } else if(size !== "responsive") {
- size = size.split("x");
- } else {
- responsive = true;
- size = "640x360";
- size = size.split("x");
- }
- var html = '<br><br>';
- if(responsive === true) {
- html += '<div class="videoEmbed" style="position:relative;height:0;padding-bottom:56.25%">';
- }
- var allowfullscreen = 'webkitallowfullscreen mozallowfullscreen allowfullscreen';
- if(video.platform === "YouTube") {
- var youtubeDomain = (settings.youtubeCookies ? 'www.youtube.com' : 'www.youtube-nocookie.com');
- html += '<iframe src="https://' + youtubeDomain + '/embed/' + video.id + '?ecver=2" width="' + size[0] + '" height="' + size[1] + '" frameborder="0"' + (responsive === true ? ' style="position:absolute;width:100%;height:100%;left:0"' : '') + ' ' + allowfullscreen + '></iframe>';
- success = true;
- } else if(video.platform === "Vimeo") {
- html += '<iframe src="https://player.vimeo.com/video/' + video.id + '" width="' + size[0] + '" height="' + size[1] + '" frameborder="0"' + (responsive === true ? ' style="position:absolute;width:100%;height:100%;left:0"' : '') + ' ' + allowfullscreen + '></iframe>';
- success = true;
- } else if(video.platform === "Facebook") {
- html += '<iframe src="https://www.facebook.com/plugins/video.php?href=' + encodeURI(url) + '&show_text=0&width=' + size[0] + '" width="' + size[0] + '" height="' + size[1] + '" style="' + (responsive === true ? 'position:absolute;width:100%;height:100%;left:0;border:none;overflow:hidden"' : 'border:none;overflow:hidden') + '" scrolling="no" frameborder="0" allowTransparency="true" ' + allowfullscreen + '></iframe>';
- success = true;
- } else if(video.platform === "Dailymotion") {
- html += '<iframe frameborder="0" width="' + size[0] + '" height="' + size[1] + '" src="//www.dailymotion.com/embed/video/' + video.id + '"' + (responsive === true ? ' style="position:absolute;width:100%;height:100%;left:0"' : '') + ' ' + allowfullscreen + '></iframe>';
- success = true;
- }
- if(responsive === true) {
- html += '</div>';
- }
- html += '<br><br>';
- if(success) {
- return html;
- }
- return false;
- }
- /**
- * Returns the unique video ID
- * @param {string} url
- * return {object|boolean}
- **/
- function getVideoID(url) {
- var vimeoRegExp = /(?:http?s?:\/\/)?(?:www\.)?(?:vimeo\.com)\/?(.+)/;
- var youtubeRegExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
- var facebookRegExp = /(?:http?s?:\/\/)?(?:www\.)?(?:facebook\.com)\/.*\/videos\/[0-9]+/;
- var dailymotionRegExp = /(?:http?s?:\/\/)?(?:www\.)?(?:dailymotion\.com)\/video\/([a-zA-Z0-9]+)/;
- var youtubeMatch = url.match(youtubeRegExp);
- var vimeoMatch = url.match(vimeoRegExp);
- var facebookMatch = url.match(facebookRegExp);
- var dailymotionMatch = url.match(dailymotionRegExp);
- if (youtubeMatch && youtubeMatch[2].length === 11) {
- return {
- "platform": "YouTube",
- "id": youtubeMatch[2]
- };
- } else if(vimeoMatch && vimeoMatch[1]) {
- return {
- "platform": "Vimeo",
- "id": vimeoMatch[1]
- };
- } else if(facebookMatch && facebookMatch[0]) {
- return {
- "platform": "Facebook",
- "id" : facebookMatch[0]
- };
- } else if(dailymotionMatch && dailymotionMatch[1]) {
- return {
- "platform": "Dailymotion",
- "id" : dailymotionMatch[1]
- };
- }
- return false;
- }
- /**
- * Fix the first line as by default the first line has no tag container
- */
- function fixFirstLine() {
- if($editor && !$editor.find(".richText-editor").html()) {
- // set first line with the right tags
- if(settings.useParagraph !== false) {
- $editor.find(".richText-editor").html('<p><br></p>');
- } else {
- //$editor.find(".richText-editor").html('<div><br></div>');
- $editor.find(".richText-editor").html('');
- }
- } else {
- // replace tags, to force <div> or <p> tags and fix issues
- if(settings.useParagraph !== false) {
- $editor.find(".richText-editor").find('div:not(.videoEmbed)').replaceWith(function() {
- return $('<p />', {html: $(this).html()});
- });
- } else {
- $editor.find(".richText-editor").find('p').replaceWith(function() {
- return $('<div />', {html: $(this).html()});
- });
- }
- }
- updateTextarea();
- }
- return $(this);
- };
- $.fn.unRichText = function( options ) {
- // set default options
- // and merge them with the parameter options
- var settings = $.extend({
- delay: 0 // delay in ms
- }, options);
- var $editor, $textarea, $main;
- var $el = $(this);
- /**
- * Initialize undoing RichText and call remove() method
- */
- function init() {
- if($el.hasClass('richText')) {
- $main = $el;
- } else if($el.hasClass('richText-initial') || $el.hasClass('richText-editor')) {
- $main = $el.parents('.richText');
- }
- if(!$main) {
- // node element does not correspond to RichText elements
- return false;
- }
- $editor = $main.find('.richText-editor');
- $textarea = $main.find('.richText-initial');
- if(parseInt(settings.delay) > 0) {
- // a delay has been set
- setTimeout(remove, parseInt(settings.delay));
- } else {
- remove();
- }
- }
- init();
- /**
- * Remove RichText elements
- */
- function remove() {
- $main.find('.richText-toolbar').remove();
- $main.find('.richText-editor').remove();
- $textarea
- .unwrap('.richText')
- .data('editor', 'richText')
- .removeClass('richText-initial')
- .show();
- }
- };
-
- }( jQuery ));
|