Conditions | 1 |
Paths | 0 |
Total Lines | 377 |
Lines | 0 |
Ratio | 0 % |
Changes | 1 | ||
Bugs | 0 | Features | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
1 | /*! |
||
54 | (function($){ |
||
55 | $.fn.formatTxt = function(elmtcx, dfrmt_obj, dmnpl_obj, cllbck){ |
||
56 | return this.each(function(){//Aplica à um ou mais elementos de uma vez |
||
57 | var elmt_mn = $(this);//elemento instanciado - menu de edição da caixa |
||
58 | var elmt_cx = (typeof(elmtcx)!="function" ? elmtcx : elmtcx.apply(elmt_mn)); |
||
59 | var dados_obj = $.extend({}, $.fn.formatTxt.datafrmt_obj, dfrmt_obj, $.fn.formatTxt.datamnpl_obj, dmnpl_obj);//funde os objetos padrões aos objetos passados como parâmetro. O "$.extend" já valida cada objeto não usando caso seja nulo, indefinido, falso, etc. |
||
60 | elmt_mn.data("frmttxt-cx", elmt_cx);//guarda como dado no menu o elemento da caixa específico |
||
61 | elmt_cx.data("frmttxt-mn", elmt_mn);//guarda como dado na caixa o elemento do menu específico |
||
62 | var pos_limit;//variáveis globalizadas neste escopo |
||
63 | //Prepara clique nos itens de edição do menu para formatação no texto, podendo ser subitem de um grupo. Necessário usar evento "mousedown" evitando problema em "click" no IE |
||
64 | elmt_mn.on("mousedown.mnedt", ".frmttxt-mn-it", function(event){ |
||
65 | event.preventDefault();//necessário para melhoria no IE |
||
66 | event.stopPropagation();//evita que os subitens reexecutem eventos do pai |
||
67 | var elmtcxit = $(event.delegateTarget).data("frmttxt-cx"); |
||
68 | //Aplica formatação conforme o item de objeto a ser aplicado, podendo ser simples (por tipo e opcionalmente usando valor, podendo ser um método de captura) ou montando a tag completa usando método |
||
69 | var slc_obj = $.fn.formatTxt.GetSetSelectObj();//obtém objeto com os dados de seleção |
||
70 | var dfrmt = $(this).attr("data-frmt");//nome do tipo de formato |
||
71 | dados_obj[dfrmt].precall ? dados_obj[dfrmt].precall(this, slc_obj) : null;//chama o método de pre-execução (quando existe), manipulando dados e elementos antes de usá-los na formatação |
||
72 | var dval = $(this).attr("data-val");//valor do formato ou indefinido (se não existe) |
||
73 | var tp = dados_obj[dfrmt].tp;//tipo de comando (opcional) |
||
74 | var css = dados_obj[dfrmt].css;//true/false para tipo estilização (opcional) |
||
75 | var exec = true;//receberá false caso o comando não seja suportado pelo navegador |
||
76 | var execss;//receberá true/false caso seja usado e o comando para estilização seja suportado ou não pelo navegador |
||
77 | if(css){//Se for passado como "true", antes de aplicar formatação, tenta executar o comando "styleWithCSS" (não suportado pelo IE) |
||
78 | try{ |
||
79 | execss = document.execCommand("styleWithCSS", false, "true");//seta para tipo formatação por estilização, ainda retornando true/false conforme sucesso da aplicação |
||
80 | }catch(e){ execss = false; } |
||
81 | } |
||
82 | if(dados_obj[dfrmt].incall){//Se existe, chama o método de execução interna para realizar a formatação toda personalizada |
||
83 | exec = dados_obj[dfrmt].incall(this, slc_obj, execss); |
||
84 | }else{ |
||
85 | if(tp){//Simples - executa o tipo de comando a ser aplicado ao texto - "execCommand(CommandName(tp), ShowDefaultUI(false), ValueArgument(null ou informado))" |
||
86 | var vl = dados_obj[dfrmt].vl ? dados_obj[dfrmt].vl(this, slc_obj) : dval;//se valor é um método de captura usa-o passando elemento como parâmetro, senão: usa "data-val" do elemento |
||
87 | try{//Tenta executar comando e caso não seja suportado atribui 'false' à variável "exec" |
||
88 | document.execCommand(tp, false, (vl!=undefined ? vl : null));//um valor é passado ao comando ou nulo |
||
89 | }catch(e){ exec = false; } |
||
90 | }else if(dados_obj[dfrmt].vlatr){//Valores de atributo - aplica ao envólucro da seleção ou cria elemento com o atributo |
||
91 | var vlatr = dados_obj[dfrmt].vlatr(this, slc_obj);//método usa o item de menu/submenu como parâmetro e retorna uma array (['atributo', 'valor1'(opcional), 'valor2'(opcional)]) |
||
92 | var atr = vlatr[0]; var vl1 = vlatr[1]; var vl2 = vlatr[2]; |
||
93 | var elmt_slc = $(slc_obj.elmt);//elemento/envólucro da seleção |
||
94 | if(!$(slc_obj.elmt).is("[contenteditable=true]") && $(slc_obj.elmt).text() == slc_obj.txt){//Se o envolucro da seleção não é a própria caixa editável e se o texto selecionado é igual à todo o texto do envólucro detectado aplica o atributo |
||
95 | if(atr == "style"){//Para aplicar atributo de estilo: |
||
96 | var ecss = elmt_slc.css(vl1);//valor atual da propriedade css especificado ou indefinido se ainda não foi aplicado |
||
97 | if(dval == "inherit" || ecss == vl2 || ecss == dval){//Se o dado de valor do item no menu é "inherit" ou se, no elemento selecionado, o valor do estilo específico já foi aplicado (com mesmo valor informado ou dado do item): |
||
98 | elmt_slc.css(vl1, "");//retira a propriedade css informada (vl1) |
||
99 | }else{//Se o estilo ainda não foi aplicado ou valor é diferente: |
||
100 | elmt_slc.css(vl1, (vl2 ? vl2 : dval));//aplica a propriedade "css" (vl1) informada com o valor (vl2, se informado) ou com o dado de valor do item no menu (dval) |
||
101 | } |
||
102 | }else if(atr == "class"){//Para aplicar atributo de classe: |
||
103 | var cls = (vl1 ? vl1 : dval);//usa como classe o valor (vl1, se informado) ou pelo dado do item no menu (dval) |
||
104 | elmt_slc.toggleClass(cls);//se o elemento já possui a classe remove-a, senão adiciona-a |
||
105 | }else{//Para qualquer outro atributo: |
||
106 | var vl = (vl1 ? vl1 : dval);//usa como valor o vl1 (se informado) ou o dado do item no menu (dval) |
||
107 | elmt_slc.attr(atr) == vl ? elmt_slc.removeAttr(atr) : elmt_slc.attr(atr, vl);//se o elemento já possui o atributo com o mesmo valor especificado remove-o, senão adiciona ou altera com valor informado |
||
108 | } |
||
109 | }else if(slc_obj.txt){//Se seleção não possui invólucro próprio cria um "<span>" padrão com o atributo para substituição (se texto não for vazio) |
||
110 | var elmt_nv = $("<span/>", {"text": slc_obj.txt});//novo elemento padrão com o texto da seleção |
||
111 | atr == "style" ? elmt_nv.css(vl1, (vl2 ? vl2 : dval)) : elmt_nv.attr(atr, (vl1 ? vl1 : dval));//se o atributo a ser adicionado é de estilo aplica css, senão aplica como atributo comum |
||
112 | try{//Tenta executar comando e caso não seja suportado atribui 'false' à variável "exec" |
||
113 | document.execCommand("insertHTML", false, elmt_nv.prop('outerHTML'));//excuta na seleção a substituição pelo elemento novo |
||
114 | }catch(e){ exec = false; } |
||
115 | } |
||
116 | }else if(dados_obj[dfrmt].vltgc){//Tag completa. Insere no lugar do texto selecionado um elemento todo premontado //-->comparar para ver se a seleção já possui elemento com mesma tag e texto e desmontá-lo |
||
117 | var vltgc = dados_obj[dfrmt].vltgc(this, slc_obj);//passa o item de menu/submenu como parâmetro do método |
||
118 | try{//Tenta executar comando e caso não seja suportado atribui 'false' à variável "exec" |
||
119 | document.execCommand("insertHTML", false, vltgc);//usa fixamente o comando "insertHTML" (não suportado pelo IE) |
||
120 | }catch(e){ exec = false; } |
||
121 | } |
||
122 | } |
||
123 | try{//Tenta executar comando não suportado pelo IE |
||
124 | document.execCommand("styleWithCSS", false, "false");//re-seta para tipo formatação por tag's (padrão) |
||
125 | }catch(e){/*faz nada*/} |
||
126 | elmtcxit.focus();//foca na caixa de texto novamente evitando falhas no desfoque |
||
127 | //Chama o método de pós-execução (quando existe), manipulando dados e elementos após a formatação |
||
128 | if(dados_obj[dfrmt].poscall){ |
||
129 | var ret = dados_obj[dfrmt].poscall(this, slc_obj, $.fn.formatTxt.GetSetSelectObj(), exec, execss);//parâmetros: o item clicado no menu, dados da seleção inicial, dados da seleção agora, "exec" e "execss" (true/false informando se a formatação foi suportada) |
||
130 | typeof ret == "boolean" ? exec = ret : null;//se há um retorno true/false atribui ao "exec" |
||
131 | } |
||
132 | //Manipula caixa de conteúdo editável e usa a função a ser chamada após mudanças no texto (opcional) |
||
133 | cllbck != undefined ? cllbck.apply(this, [elmtcxit, slc_obj, exec]) : null;//em "apply(this, [param1, param2...])" o primeiro parâmetro refere-se ao "this" (escopo) usado na função, que é o item clicado no menu. Parâmetros: a caixa editável, dados da seleção e exec (true/false informando se o commando foi suportado) |
||
134 | //Executa o clique para ocultar submenu, filtrando pelo evento específico com rótulo ".mnedt" |
||
135 | $("body").trigger("mousedown.mnedt"); |
||
136 | }); |
||
137 | //Prepara clique nos itens de grupo do menu exibindo o elemento de submenu (dropdown) que agrupa os subitens |
||
138 | elmt_mn.find(".frmttxt-mn-drpdn").hide();//garante que todos submenus estejam ocultos |
||
139 | elmt_mn.on("mousedown.mnedt", ".frmttxt-mn-gp", function(event){ |
||
140 | event.preventDefault();//necessário para melhoria no IE |
||
141 | var wrap_drpdwn = $(this).find(".frmttxt-mn-drpdn"); |
||
142 | if(wrap_drpdwn.is(":hidden")){//Exibe submenu apenas se está oculto evitando repetições |
||
143 | $("body").trigger("mousedown.mnedt");//se algum outro está visível executa evento que oculta |
||
144 | wrap_drpdwn.show();//exibe o submenu |
||
145 | !pos_limit ? pos_limit = $(event.delegateTarget).offset().left + $(event.delegateTarget).width() : null;//guarda a posição (x, à direita) limite do elemento menu |
||
146 | if(wrap_drpdwn.css("left") != "auto" && (wrap_drpdwn.offset().left + wrap_drpdwn.width()) > pos_limit){//Após ficar visível o submenu é verificado e ajeitado caso passe do limite do menu |
||
147 | wrap_drpdwn.css({left: "auto", right: "-13px"});//inverte-se, ficando deslocado a esquerda |
||
148 | } |
||
149 | var wrap_gp = $(this);//reserva elemento do grupo |
||
150 | //Aplica evento ao "body", verificando quando o usuário clica fora do grupo, ocultando o submenu |
||
151 | $("body").off("mousedown.mnedt keydown.mnedt");//remove eventos previamente evitando acumulo dos mesmos eventos |
||
152 | $("body").on("mousedown.mnedt keydown.mnedt", function(event){//Ao qualquer elemento ser pressionado. É usado rótulo ".mnedt" para ser agora e depois: removido especificamente |
||
153 | var kcd = event.which; |
||
154 | //Verifica se o alvo não é o elemento pai do grupo ("wrap_gp") e não é um elemento filho dela |
||
155 | if(kcd == 27 || (!$(event.target).is(wrap_gp) && wrap_gp.has(event.target).length == 0)){//Filtro de exceções |
||
156 | wrap_gp.find(".frmttxt-mn-drpdn").hide();//oculta submenu |
||
157 | $("body").off("mousedown.mnedt keydown.mnedt");//remove evento, filtrando pelo evento específico com rótulo de menu (sem interferir nos outros cliques do "body") |
||
158 | $.fn.formatTxt.GetSetSelectObj(null, true);//restaura a seleção, quando guardada |
||
159 | } |
||
160 | }); |
||
161 | }else if(!$(event.target).is(wrap_drpdwn) && wrap_drpdwn.has(event.target).length == 0){//Se submenu já está visível e o item clicado não foi o submenu e filhos: oculta-o |
||
162 | wrap_drpdwn.hide();//oculta submenu |
||
163 | $.fn.formatTxt.GetSetSelectObj(null, true);//restaura a seleção, quando guardada |
||
164 | } |
||
165 | }); |
||
166 | //Prepara clique nos itens de manipulação do menu para agregar eventos extras ao fluxo principal. É necessário o vento "click" para ser executado após o usuário soltar mouse |
||
167 | elmt_mn.on("click.mnedt", ".frmttxt-mn-mp", function(event){ |
||
168 | event.stopPropagation();//evita eventos de elementos pai sejam executados |
||
169 | var elmtcxit = $(event.delegateTarget).data("frmttxt-cx"); |
||
170 | //Executa métodos conforme o item de objeto "datamnpl_obj" |
||
171 | var slc_obj = $.fn.formatTxt.GetSetSelectObj();//obtém objeto com os dados de seleção |
||
172 | var dmnpl = $(this).data("mnpl");//nome do método manipulador |
||
173 | var ret = dados_obj[dmnpl](this, slc_obj, event);//chama o método manipulando dados e elementos para usá-los nas formatações independentemente |
||
174 | //Como poderá haver alterações após execução do método: manipula a caixa de texto editável |
||
175 | ret !== false ? elmtcxit.focus() : null;//foca na caixa de texto novamente evitando falhas no desfoque, mas apenas se não retornar 'true' (booleano) |
||
176 | elmtcxit.keyup();//executa evento que detecta a formatação para destacar no menu |
||
177 | }); |
||
178 | //Ao selecionar texto (por mouse ou teclado) detecta a formatação (tags) para destacar no menu. Usa temporizador para só executar num intervalo de tempo |
||
179 | elmt_cx.on("mouseup.mnedt keyup.mnedt", function(event){ |
||
180 | var elmtmnit = $(event.delegateTarget).data("frmttxt-mn"); |
||
181 | typeof mnslc_tm != "undefined" ? clearTimeout(mnslc_tm) : null;//limpa o temporizador antes de reseta-lo |
||
182 | mnslc_tm = setTimeout(function(){ |
||
183 | elmtmnit.find(".frmttxt-mn-slcndo").removeClass('frmttxt-mn-slcndo');//remove destaque de todos elementos do menu (filhos, netos...) que possuem a classe |
||
184 | var slc_obj = $.fn.formatTxt.GetSetSelectObj();//obtém objeto com os dados de seleção |
||
185 | if(slc_obj && !$(slc_obj.elmt).is("[contenteditable=true]")){//Só entra se há seleção e se o envolucro da seleção não é a própria caixa editável |
||
186 | //Aplica classe de destaque aos elementos do menu comparando "tag" do texto selecionado com as tags de referência (alguns possuem tags altenativas para diferentes navegadores e/ou formas de formatação) |
||
187 | var tg_ar, tg_vl; |
||
188 | for(var prop in dados_obj){//Varre o objeto passando por cada propriedade |
||
|
|||
189 | tg_ar = dados_obj[prop].tg;//array de tags |
||
190 | if(tg_ar){//Se o item possui tags de referência |
||
191 | for(i=0; i<tg_ar.length; i++){ |
||
192 | if(typeof tg_ar[i]=="string" && tg_ar[i]==slc_obj.tag){//Tag simples - verifica nome somente [ex.: <b>, <i>, <u>, ...] |
||
193 | elmtmnit.find("[data-frmt="+prop+"]").addClass('frmttxt-mn-slcndo');//aplica o destaque ao item conforme nome da formatação (propriedade) |
||
194 | break;//bateu com uma tag da propriedade atual - sai do loop filho |
||
195 | }else if(tg_ar[i].nm == slc_obj.tag || tg_ar[i].nm === null){//Tag com subitens ({nm:"*", atr:"*", ext:"*"}) - verifica na seleção: nome de tag(pode valer 'null'), atributo, podendo ter dado extra. Se o objeto de tag tem o "nm" igual a 'null' aceita qualquer nome de tag |
||
196 | tg_vl = $(slc_obj.elmt).attr(tg_ar[i].atr);//obtém o valor do atributo informado ou indefinido (se o elemento não o possui). |
||
197 | if(tg_vl){//Se há um valor (o atributo bateu com o do elemento) |
||
198 | if(tg_ar[i].atr == "style"){//Se é atributo estilo: captura o valor pelo dado extra |
||
199 | tg_vl = $(slc_obj.elmt).prop("style")[tg_ar[i].ext];//captura no estilo do elemento selecionado: o valor da propriedade especificada |
||
200 | if(!tg_vl){//Se for invalido pula para a próxima tag |
||
201 | continue; |
||
202 | } |
||
203 | }else if(tg_ar[i].atr == "class"){//Se é atributo de classe usa a classe informada (extra) |
||
204 | if(tg_ar[i].ext && $(slc_obj.elmt).hasClass(tg_ar[i].ext)){//Se a classe foi especificada e existe no elemento usa-a como valor |
||
205 | tg_vl = tg_ar[i].ext; |
||
206 | }else{//Se classe não existe pula para a próxima tag |
||
207 | continue; |
||
208 | } |
||
209 | } |
||
210 | elmtmnit.find("[data-frmt='"+prop+"'][data-val='"+tg_vl+"']").addClass('frmttxt-mn-slcndo');//aplica o destaque ao item do menu |
||
211 | break;//bateu com uma tag da propriedade atual - sai do loop filho |
||
212 | } |
||
213 | } |
||
214 | } |
||
215 | } |
||
216 | }; |
||
217 | } |
||
218 | }, 200); |
||
219 | }); |
||
220 | //Na caixa, limpa formatação ao colar texto |
||
221 | elmt_cx.on("paste.mnedt", function(event){ |
||
222 | event.preventDefault(); |
||
223 | var cntd; |
||
224 | if(event.originalEvent.clipboardData){//Verifica se existe dados de cópia na memória |
||
225 | cntd = (event.originalEvent || event).clipboardData.getData('text/plain');//captura o conteúdo copiado |
||
226 | document.execCommand("insertText", false, cntd);//insere o conteúdo |
||
227 | }else if(window.clipboardData){//Verifica dados de cópia na memória (para IE) |
||
228 | cntd = window.clipboardData.getData('Text');//captura o conteúdo copiado |
||
229 | if(window.getSelection){ |
||
230 | window.getSelection().getRangeAt(0).insertNode(document.createTextNode(cntd));//insere o conteúdo |
||
231 | }else{ |
||
232 | document.selection.createRange().pasteHTML(cntd);//insere o conteúdo |
||
233 | } |
||
234 | } |
||
235 | }); |
||
236 | //Na caixa, ao usuário teclar 'tab' insere código de espaço equivalente no html, sem deixar perder o foco |
||
237 | elmt_cx.on("keydown.mnedt", function(event){ |
||
238 | var kcd = event.which;//o "which" da jQuery normaliza os códigos de tecla independente do tipo de evento |
||
239 | if(kcd == 9){//código da tecla "tab" |
||
240 | event.preventDefault();//impede a aplicação padrão da tecla (foco no próximo elemento) |
||
241 | try{//Tenta executar commando padrão do "JavaScript" de inserção de texto (não suportado no IE) |
||
242 | document.execCommand("insertHtml", false, " "); |
||
243 | }catch(e){//Se não funcionou insere pelo método de seleção |
||
244 | $.fn.formatTxt.GetSetSelectObj(" ");//insere quatro espaços |
||
245 | } |
||
246 | } |
||
247 | }); |
||
248 | }); |
||
249 | }; |
||
250 | |||
251 | //Função captura dados do trecho selecionado/posicionado pelo usuário e retorna como objeto. Os parâmetros são para inserção de texto e restauração de seleção de 'range' |
||
252 | $.fn.formatTxt.range = null; |
||
253 | $.fn.formatTxt.GetSetSelectObj = function(txt, rng){ |
||
254 | var slc_rng, slc_elmt, slc_tag, slc_txt, vrtxt = (txt && typeof txt == "string"); |
||
255 | if(window.getSelection){ |
||
256 | var slctn = window.getSelection(); |
||
257 | if(slctn.rangeCount){ |
||
258 | slc_rng = slctn.getRangeAt(0); |
||
259 | var node = slc_rng.commonAncestorContainer; |
||
260 | slc_txt = slctn.toString(); |
||
261 | slc_elmt = node.nodeType == 1 ? node : node.parentNode; |
||
262 | if(slc_txt && slc_elmt.textContent != slc_txt){//Se não bateu com texto selecionado. Para navegadores como Firefox que não detectam o envólucro imediato |
||
263 | var ncntnr = slctn.getRangeAt(0).startContainer.nextSibling; |
||
264 | slc_elmt = (ncntnr && ncntnr.textContent == slc_txt ? ncntnr : slc_elmt); |
||
265 | } |
||
266 | slc_tag = (slc_elmt.nodeType == 1 ? slc_elmt.nodeName : slc_elmt.parentNode.nodeName); |
||
267 | if(vrtxt){//Se foi passado texto para inserção, insere-o |
||
268 | slc_rng.deleteContents(); |
||
269 | slc_rng.insertNode(document.createTextNode(txt)); |
||
270 | } |
||
271 | if(rng == true && $.fn.formatTxt.range){//Se foi requisitado e há "range" (trecho) reservado: restaura seleção |
||
272 | slctn.removeAllRanges(); |
||
273 | slctn.addRange($.fn.formatTxt.range); |
||
274 | $.fn.formatTxt.range = null;//anula reserva de "range" novamente |
||
275 | } |
||
276 | }else{ |
||
277 | return null; |
||
278 | } |
||
279 | }else if(document.selection && document.selection.type != "Control"){//Para IE |
||
280 | slc_rng = document.selection.createRange(); |
||
281 | slc_elmt = slc_rng.parentElement(); |
||
282 | slc_txt = slc_rng.text; |
||
283 | slc_tag = slc_rng.parentElement().nodeName; |
||
284 | vrtxt ? slc_rng.text = txt : null;//se informado texto, insere-o |
||
285 | if(rng == true && $.fn.formatTxt.range){//Se foi requisitado e há "range" (trecho) reservado: restaura seleção |
||
286 | $.fn.formatTxt.range.select(); |
||
287 | $.fn.formatTxt.range = null;//anula reserva de "range" novamente |
||
288 | } |
||
289 | }else{ |
||
290 | return null; |
||
291 | } |
||
292 | return {rng: slc_rng, elmt: slc_elmt, tag: slc_tag, txt: slc_txt}; |
||
293 | } |
||
294 | //Função para alterar elemento(s) podendo-se mudar a tag/elemento, assim como adicionar e remover atributos, opcionalmente |
||
295 | $.fn.formatTxt.altrElmnt = function(elmt, nelmt, atr_ad, atr_rm){ |
||
296 | elmt.each(function(){ |
||
297 | if(atr_ad){//Se há array de atributos a serem adicionados: |
||
298 | for(i=0; i<atr_ad.length; i++){ |
||
299 | var atr = atr_ad[i].atr; |
||
300 | var vl1 = (typeof atr_ad[i].vl1 != "function" ? atr_ad[i].vl1 : atr_ad[i].vl1(this)); |
||
301 | if(atr == "style"){//Se é atributo de estilo inclui por "css()" usando dois valores |
||
302 | var vl2 = (typeof atr_ad[i].vl2 != "function" ? atr_ad[i].vl2 : atr_ad[i].vl2(this)); |
||
303 | $(this).css(vl1, vl2); |
||
304 | }else if(atr == "class"){//Se é atributo de classe inclui valor por "addClass()" |
||
305 | $(this).addClass(vl1); |
||
306 | }else{//Se é atributo comum inclui valor |
||
307 | $(this).attr(atr, vl1); |
||
308 | } |
||
309 | } |
||
310 | } |
||
311 | if(atr_rm){//Se há array de atributos a serem removidos: |
||
312 | for(i=0; i<atr_rm.length; i++){ |
||
313 | $(this).removeAttr(atr_rm[i]); |
||
314 | } |
||
315 | } |
||
316 | if(nelmt){//Se foi passado novo elemento, substitui pela tag informada |
||
317 | var atrs = {}; |
||
318 | $.each($(this)[0].attributes, function(idx, atr){//Reserva os atributos do elemento |
||
319 | atrs[atr.nodeName] = atr.nodeValue; |
||
320 | }); |
||
321 | //Substitui o elemento pelo novo, com todos os atributos e conteúdo |
||
322 | $(this).replaceWith( $("<"+nelmt+"/>", atrs).append($(this).contents()) ); |
||
323 | } |
||
324 | }); |
||
325 | } |
||
326 | //Função para matar aplicações do plugin nos filhos do elemento (ou coleção de elementos) de menu e de cada caixa editável. Remove eventos com o rótulo "mnedt" e outros dados |
||
327 | $.fn.formatTxt.destroy = function(elmt){//O elemento do parâmetro deve ser um menu que tenha sido instanciado anteriormente |
||
328 | $("body").trigger("mousedown.mnedt");//oculta submenus |
||
329 | elmt.off(".mnedt");//remove eventos do(s) menu(s) |
||
330 | elmt.find("*").off(".mnedt");//remove eventos dos filhos do(s) menu(s) |
||
331 | elmt.find(".frmttxt-mn-slcndo").removeClass('frmttxt-mn-slcndo');//remove destaques do(s) menu(s) |
||
332 | elmt.each(function(){//Usa o elemento da caixa editável reservado em cada menu |
||
333 | var elmtcxit = $(this).data("frmttxt-cx"); |
||
334 | elmtcxit.off(".mnedt");//remove eventos da caixa |
||
335 | elmtcxit.find("*").off(".mnedt");//remove eventos dos filhos da caixa |
||
336 | elmtcxit.removeData("frmttxt-mn");//remove o dado com o elemento de menu reservado na caixa |
||
337 | }); |
||
338 | elmt.removeData("frmttxt-cx");//remove o dado com o elemento de caixa reservado na(s) caixa(s) |
||
339 | } |
||
340 | |||
341 | /*- Cada item (propriedade) é um rótulo para a formatação e o elemento do menu deverá ter o mesmo em "data-frmt='nome'", ex.: "ngrto" para aplicação de negrito. |
||
342 | - O subitem "precall" (quando necessário) é um método de pre-execução chamado para manipular dados e elementos antes de usá-los na formatação, podendo alterar até mesmo os próprios dados do objeto (ex.: usando formatação de cor, antes de executar, é verificado se foi selecionado aplicação de cor no texto ou no fundo, alterando o subitem de tipo de formatação "tp"), o "incall" executa internamente para quando se quer aplicar formatação de uma maneira totalmente personalizada e o "poscall" faz o mesmo mas ao final das execuções principais e por isso pode ser usado para solucionar execuções não suportadas (nesse caso deve-se retornar true/false conforme funcionamento). |
||
343 | - O subitem "tp" é o nome do tipo padrão de comando a ser aplicado como formatação. Quando não usado, a formatação usará apenas o subitem "vlatr" ou "vltgc". |
||
344 | - O subitem "tg" possui array com as tags (em maiúsculo) de referência para a tag que a formatação cria e para, ao usuário selecionar texto, destacar o elemento do menu correspondente (ex.:"B" para <b> procurará elemento com data-frmt="ngrto"), podendo ser várias (navegadores podem criar diferentes tags) e quando a mesma formatação possui valores diferentes (como tamanhos de fonte) e/ou é aplicada usando os métodos de valor ("vlatr" ou "vltgc") "tg" poderá ter objetos com 'nome', 'atributo', podendo possuir ainda propriedade 'extra' para style ou valor específico de classe, ex.: {nm:"SPAN", atr:"style", ext:"font-size"} ou {nm:"DIV", atr:"class", ext:"formato-1"}. O 'extra' para atributo "style" deverá seguir o padrão do método "css()" da jQuery (ex.: "borderTopWidth" para borda superior). |
||
345 | - Quando se quer aplicar valor o item (elemento) do menu deverá possuir "data-val='valor'" e o valor deverá ser "inherit" para os casos em que se quer remoção de estilo específico. O subitem "vl" é um método para capturar valor dinamicamente (como a cor) sem se usar "data-val='valor'". O subitem "vlatr" retorna uma array com um 'atributo' (índice 0), 'valor1' (2, opcional) e 'valor2' (3, opcional - fixo ou capturado se não for usado o "data-val='valor'") para ser aplicado ao trecho selecionado, ex.: ["style", "color", mnit.css("color")], se "tg" for usado deverá ter o "nm" valendo "null" pois o atributo poderá ser aplicado a qualquer elemento que circunda a seleção. O método "vltgc" é para substituir a seleção por uma tag completa (incluindo o texto), ex.: para uma linha: "<hr>" ou para uma citação: "<blockquote>texto</blockquote>". Nos casos de uso de "vlatr" e "vltgc" o subitem "tp" não será usado. |
||
346 | - O subitem "css" deverá ser incluído valendo "true" quando se quer que a formatação aconteça por meio de estilização ou como no caso de criação de lista (que ajeita o tamanho dos subelementos) altere filhos por estilização. É útil para tipos de comandos que criam por padrão tag's não suportadas em HTML5, como a criação de "<font...>" (obsoleto) para cor e tamanho. Seu uso limita a comparação de tag com valor (para destaque) em alguns casos, nos quais deverá ser usado o método "vlatr" ou "vltgc" para aplicar a formatação*/ |
||
347 | $.fn.formatTxt.datafrmt_obj = { |
||
348 | ngrto: {tp:"bold", tg:["B", "STRONG"]}, itlco: {tp:"italic", tg:["I", "EM"]}, sblnhdo: {tp:"underline", tg:["U"]}, |
||
349 | rscdo: {tp:"strikeThrough", tg:["STRIKE"]}, sbrscrto: {tp:"superscript", tg:["SUP"]}, sbscrto: {tp:"subscript", tg:["SUB"]}, |
||
350 | sbrlnhdo: {tg:[{nm:null, atr:"style", ext:"text-decoration"}], vlatr: function(mnit, slc){ return ["style", "text-decoration"]; }}, |
||
351 | insrcrctr: {tp:"insertText", vl: function(mnit, slc){ return $(mnit).text(); }, poscall: function(mnit, slc, nslc, exc, excs){ |
||
352 | //Uma vez que a inserção de texto pelo comando "document.execCommand("insertText", ...)" não é suportado pelo IE: |
||
353 | if(exc == false){//Usa a função 'cross-browser' de seleção, para inserir |
||
354 | return ($.fn.formatTxt.GetSetSelectObj($(mnit).text()) ? true : false);//retorna true/false conforme funcionamento |
||
355 | } |
||
356 | }}, |
||
357 | tplist1: {tp:"insertUnorderedList", css: true}, tplist2: {tp:"insertOrderedList", css: true}, |
||
358 | fnttmnho: {tg:[{nm:null, atr:"style", ext:"font-size"}], vlatr: function(mnit, slc){ return ["style", "font-size"]; }}, |
||
359 | txtcor: {precall: function(mnit, slc){ |
||
360 | this.tp = ($(mnit).parents(".frmttxt-mn-drpdn").find(".frmttxt-mn-mp input:checked").val() == "1" ? "foreColor" : "backColor"); |
||
361 | }, tp:"foreColor", tg:[{nm:null, atr:"style", ext:"color"}], css: true, poscall: function(mnit, slc, nslc, exc, excs){ |
||
362 | if(excs == false && nslc.tag == "FONT"){//Se formatação não foi aplicada com estilização e foi criado um elemento "<font>" (para IE): |
||
363 | /*this.tg[0].nm = "FONT"; this.tg[0].atr = "color"; this.tg[0].ext = null;//altera padrões da tag de comparação |
||
364 | var mnitval = $(mnit).attr("data-val"); $(mnit).attr("data-val", mnitval.replace(/\s/g, ""));//retira do valor os espaços conforme padrão da tag <font>: 'rgb(235,107,86)'*/ |
||
365 | if(this.tp == "foreColor"){//Se foi aplicado cor de texto substitui por um "<span>" com estilo da mesma cor |
||
366 | $.fn.formatTxt.altrElmnt($(nslc.elmt), "span", [{atr:"style", vl1:"color", vl2:$(nslc.elmt).attr("color")}], ["color"]); |
||
367 | }else{//Se foi aplicado cor de fundo substitui por um "<span>" (já foi aplicado com estilo) |
||
368 | $.fn.formatTxt.altrElmnt($(nslc.elmt), "span"); |
||
369 | } |
||
370 | } |
||
371 | }}, |
||
372 | insrlnk: {precall: function(mnit, slc){ |
||
373 | var inp_elmt = $(mnit).parents(".frmttxt-mn-drpdn").find("input"); var val_txt = inp_elmt.val(); |
||
374 | inp_elmt.val((/^([a-zA-Z0-9+.-]+):\/\//i).test(val_txt) || val_txt=="" ? val_txt : "http://"+val_txt);//verifica se há protocolo na url e insere "http://" por padrão |
||
375 | $.fn.formatTxt.GetSetSelectObj(null, true);//restaura a seleção guardada para formatação do mesmo trecho |
||
376 | }, tp:"createLink", vl: function(mnit, slc){ return $(mnit).parents(".frmttxt-mn-drpdn").find("input").val(); }, poscall: function(mnit, slc, nslc, exc, excs){ |
||
377 | var inp_elmt = $(mnit).parents(".frmttxt-mn-drpdn").find("input"); |
||
378 | if(inp_elmt.val()){//Se o valor do input é valido: |
||
379 | !this.tp ? $(nslc.elmt).attr("href", inp_elmt.val()) : null;//se o "tp" está anulado (quando há link focado mas não selecionado) apenas altera a "url" |
||
380 | $(nslc.elmt).attr("target", "_blank");//após criar link adiciona "target" para nova aba ao clicar |
||
381 | $(mnit).parents(".frmttxt-mn-drpdn").find("input").val("");//apenas limpa o texto do "input" após formatação |
||
382 | } |
||
383 | }}, |
||
384 | rmvlnk: {precall: function(mnit, slc){ |
||
385 | slc.tag=="A" && slc.txt=="" ? this.tp = null : null;//anula o tipo de formatação quando há link focado mas não selecionado, para pular direto para o "poscall()" |
||
386 | },tp:"unlink", tg:["A"], poscall: function(mnit, slc, nslc, exc, excs){ |
||
387 | if(slc.tag=="A" && !this.tp){//Se o "tp" está anulado (quando há link focado mas não selecionado): |
||
388 | $(slc.elmt).replaceWith($(slc.elmt).text());//remove link substituindo o elemento por seu texto |
||
389 | this.tp = "unlink";//retorna o tipo de formatação |
||
390 | } |
||
391 | }}, |
||
392 | lmpfrmt: {tp:"removeFormat"} |
||
393 | /*, simplescaptura: {tp:"insertText", vl: function(mnit){ return $(mnit).text();}}, |
||
394 | atributo-css: {tg:[{nm:null, atr:"style", ext:"text-decoration"}], vlatr: function(mnit){ return ["style", "text-decoration"]; }}, |
||
395 | atributo-class: {tg:[{nm:null, atr:"class", ext:"sobrelinhado"}], vlatr: function(mnit){ return ["class"]; }}, |
||
396 | tagcompleta: {tg:["BLOCKQUOTE"], vltgc: function(mnit, slc){ return "<blockquote>"+(slc.txt || "...")+"</blockquote>"; }}*/ |
||
397 | } |
||
398 | /*- Para eventos extras do menu pode-se usar o objeto "datamnpl_obj" de métodos para anexar manipulações ao fluxo principal de formatações e independente delas. Ex.: a formatação de cor necessita de um manipulador para alterar o valor de destaque (dstq:{atr:"style", ext:"color"}) entre cor do texto ("color") e cor do fundo ("background-color") verificando qual foi selecionado pelo usuário. |
||
399 | - Os nomes/rótulos dos métodos devem ser diferentes dos nomes de propriedade em "datafrmt_obj" uma vez que, no instanciamento, eles são unidos num só objeto, permitindo manipulação de todos os dados. O uso de 'this' nos métodos refere-se ao objeto pai "dados_obj" criado no instanciamento.*/ |
||
400 | $.fn.formatTxt.datamnpl_obj = { |
||
401 | txtcortp: function(mnmp, slc){//Para cores |
||
402 | var chk = $(mnmp).children("input:checked").val();//opção selecionada pelo usuário |
||
403 | this.txtcor.tg[0].ext = (chk == "1" ? "color" : "background-color");//altera o valor de comparação para destaque |
||
404 | $(mnmp).parents(".frmttxt-mn-drpdn").find(".frmttxt-mn-it.rmv").attr("data-val", (chk == "1" ? "#888888" : "inherit"));//altera o valor usado no item que simula remoção de cor, usando a cor padrão para cor de texto e "inherit" para cor de fundo |
||
405 | }, |
||
406 | insrlnkvl: function(mnmp, slc, evnt){//Para inserção de caracteres |
||
407 | var inp_elmt = $(mnmp).find("input"); |
||
408 | if(inp_elmt.is(":visible")){//Se o "input" estiver visível: |
||
409 | if(slc && !$(evnt.target).is(inp_elmt)){//Se há seleção e "input" não foi clicado depois de já visível: |
||
410 | $.fn.formatTxt.range = slc.rng;//reserva o "range" (trecho) selecionado antes de perder foco |
||
411 | this.insrlnk.tp = (slc.tag=="A" && slc.txt=="" ? null : "createLink");//se uma tag de link foi focado, mas não selecionada, anula o "tp" (tipo de comando) da formatação "insrlnk", obrigando a alteração apenas do "href" pelo método "vlatr" |
||
412 | var val_txt = (slc.tag=="A" ? $(slc.elmt).attr("href") : "");//verifica se o elemento selecionado já é link, capturando a url ou vazio |
||
413 | inp_elmt.val(val_txt).focus();//inlui texto e foca no "input" |
||
414 | } |
||
415 | if(!$._data(inp_elmt[0], "events")){//Se ainda não foi aplicado o evento de tecla ao input: |
||
416 | inp_elmt.on("keydown.mnedt", function(event){//Ao pressionar alguma tecla, verifica: |
||
417 | var kcd = event.which; |
||
418 | if(kcd == 13){//código da tecla "enter" |
||
419 | event.preventDefault();//impede a aplicação padrão da tecla (foco no próximo elemento) |
||
420 | inp_elmt.val() ? $(this).parent().children(".frmttxt-mn-it").mousedown() : null;//se link é valido executa o evento de formatação já aplicado ao botão "ok" |
||
421 | } |
||
422 | }); |
||
423 | } |
||
424 | return false;//retorna 'false' para evitar que a caixa editável seja focada saindo do "input" |
||
425 | }else{ |
||
426 | inp_elmt.val("");//apenas limpa o "input" ao ocultar |
||
427 | } |
||
428 | } |
||
429 | } |
||
430 | }(jQuery)); |
||
431 |
When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically: