User:Ciencia Al Poder-fduser/CharInsert/en

This is a MediaWiki extension that allows a highly customization to the characters that usually are put below the edit box to give an easy way to insert some strange or repeatedly pieces of text into the edit box.

Features

 * Is fully functional in Mozilla Firefox, Opera and Internet Explorer, and with any browser that supports the standards DOM Level 1 and DOM Level 2 Events.
 * You can define groups of characters in both the HTML of the page and with JavaScript with an easy manner.
 * The different groups of characters are not displayed unless you select one of them with a select input. The select input only is displayed when there's more than one group of characters.
 * When selecting one of the groups with the select input, the group selected is stored in a temporary cookie that reminds the last group selected and automatically switches to it when the page is reloaded.
 * Module-based load: The character groups defined by javascript are loaded in the document only when they are selected in the select input, not before. This reduces the time to load the page, in case that there was a lot of character groups to load.
 * The design is fully customizable with CSS
 * Object-oriented programming designed as an individual class, that avoids conflicts with functions and variables with common names.

License
http://www.gnu.org/copyleft/gpl.html GNU General Public Licence 2.0 or later.

Pre-requisites
To insert text in the edit box, this extension uses the insertTags function, defined in the file wikibits.js (Commonly included in all MediaWiki installations)

JavaScript
There must be declared the unique global variable of this utility (in MediaWiki:Common.js, user Special:Mypage/monobook.js or similar) before that any of the code of this extension is executed:

var charInsert = {groups: {}};

After that, you can put the implementations of the functions of this utility and JavaScript-defined character groups (as described in basic customization), without care of the order, but it's recommended to load the JavaScript-defined character groups after that any user-JavaScript file is loaded, so the user could overwrite the character groups defined in the site. As an example of JavaScript Character group definition:

 charInsert.groups["MediaWiki"] = [ '~', [], [,], [], ['#REDIRECT ',], [' '], ' ', [' ',' '], [' ',' '], ['&lt;nowiki>','&lt;/nowiki>'], [], ['',''], ''];

Also, you must define the ID of the element where this utility would be initiated, where the character groups will be inserted and activating the characters defined in the HTML.

Once doing that, the JavaScript functions of this utility must be declared, as follows:

// Author: Jesús Martínez Novo (Ciencia Al Poder) // Licencia/License: http://www.gnu.org/copyleft/gpl.html GNU General Public Licence 2.0 or later // To add groups of special characters, add new identifiers to the object charInsert.groups as array elements. If an element is an other array, then it will be treated as a double element. // sample: charInsert.groups["Name of the group"] = ['a','b','c', ['d','e'], ['f','g'] ]; // To disable storing in a cookie the chargroup selected // charInsert.disableCookie = true;

charInsert.version = '1.1';

charInsert.bindId = 'charinsert-blocks'; // ID of the element where this utility would be placed. Change if necessary

charInsert.activaCaracteresEspeciales = function { if (!document.createTextNode) return; // No es DOM compatible var divSC = document.getElementById(charInsert.bindId); if (!divSC) return; // 1. Añadimos una caja de selección segn los conjuntos de caracteres que hay var select = document.createElement('select'); select.id = 'chargroup-select'; // 1.1 Conjuntos de caracteres que ya haya en el código var listaCharGrp = divSC.getElementsByTagName('div'); for (var i = 0; i < listaCharGrp.length; i++){ var p = listaCharGrp[i]; if ((' chargroup ').indexOf(' '+p.className+' ') != -1){ var option = document.createElement('option'); option.value = p.title; option.groupRef = p;     option.appendChild(document.createTextNode(p.title)); select.appendChild(option); p.title = ''; // Borramos el título para que no aparezca al pasar el mouse por encima // IE Fix: la selección actual en el textarea se pierde si se hace clic en un elemento que no sea un 'a' o un elemento de formulario ('input', etc) if (document.selection && !is_gecko){ var el = p.firstChild; if (el) { do { if (el.nodeType == 1 && el.tagName.toLowerCase == 'span') { var inel = el.firstChild; if (!inel) continue; var a = document.createElement('a'); a.href = '#'; do { var refinel = inel; inel = inel.nextSibling a.appendChild(refinel); } while (inel); el.appendChild(a); }         } while (el = el.nextSibling); }     }      // Fin IE Fix } }  // 1.2 Conjuntos de caracteres definidos en charInsert.groups (custom) if (typeof charInsert.groups == typeof {}){ for (grupo in charInsert.groups){ var option = document.createElement('option'); option.value = grupo; option.groupRef = null; option.groupArray = charInsert.groups[grupo]; option.appendChild(document.createTextNode(grupo)); select.appendChild(option); } }

if (select.options.length > 1){ divSC.insertBefore(select, divSC.firstChild); // 2. Capturamos el evento de cambio charInsert.addEvent(select, 'change', charInsert.eSelectChanged); // 3. Seleccionamos grupo por defecto var selectedGrp = select.options[0].value; if (charInsert.disableCookie == undefined || charInsert.disableCookie != true){ var cookie = document.cookie; var cookiePos = cookie.indexOf('chargroup='); if (cookiePos > -1) { cookiePos += 10; var endPos = cookie.substring(cookiePos,cookie.length).indexOf(';'); if (endPos == -1) endPos = cookie.length; selectedGrp = decodeURIComponent(document.cookie.substr(cookiePos,endPos)); }   }    select.value = selectedGrp; charInsert.selectChargroup(select.options[select.selectedIndex]); }else{ delete select; }

// 4. Asignamos un evento para todo el area charInsert.addEvent(divSC, 'click', charInsert.specialCharClick); };

charInsert.eSelectChanged = function(event){ var targetElement = charInsert.eventTargetElement(event); charInsert.selectChargroup(targetElement.options[targetElement.selectedIndex]); if (charInsert.disableCookie == undefined || charInsert.disableCookie != true) document.cookie = 'chargroup='+encodeURIComponent(targetElement.options[targetElement.selectedIndex].value); };

charInsert.selectChargroup = function(item){ var divSC = document.getElementById(charInsert.bindId); if (!divSC) return;

var listaCharGrp = divSC.getElementsByTagName('div'); for (var i = 0; i < listaCharGrp.length; i++){ var p = listaCharGrp[i]; if ((' '+p.className+' ').indexOf(' chargroup ') != -1){ if ((p.isSameNode && p.isSameNode(item.groupRef)) || p == item.groupRef){ //DOM || IE       p.style.display = 'inline'; }else{ p.style.display = 'none'; }   }  }  if (!item.groupRef && item.groupArray){ var p = charInsert.addGroup(item.groupArray); item.groupRef = p;   p.style.display = 'inline'; } };

charInsert.addGroup = function(group){ var divSC = document.getElementById(charInsert.bindId); if (!divSC) return; var bloque = document.createElement('div'); bloque.className = 'chargroup'; for (var i = 0; i < group.length; i++){ // IE Patch if (document.selection && !is_gecko){ var car = document.createElement('a'); car.href = "#"; } else // END IE Patch var car = document.createElement('span'); if (typeof group[i] == typeof ''){ car.appendChild(document.createTextNode(group[i])); }else if(typeof group[i] == typeof [] && group[i].length == 2){ var c1 = document.createElement('span'); c1.appendChild(document.createTextNode(group[i][0])); car.appendChild(c1); var c2 = document.createElement('span'); c2.appendChild(document.createTextNode(group[i][1])); car.appendChild(c2); }   // IE Patch if (document.selection && !is_gecko){ var ospan = document.createElement('span'); ospan.appendChild(car); bloque.appendChild(ospan); } else // END IE Patch bloque.appendChild(car); bloque.appendChild(document.createTextNode(' ')); } divSC.appendChild(bloque); return bloque; };

charInsert.specialCharClick = function(event){ var charEl = charInsert.eventTargetElement(event); // Obtenemos el span más externo posible, pero que descienda directamente del div de class 'chargroup' // Si lo capta un textNode (no debería), buscamos su span. if (charEl.nodeType == 3){ // text node. if (charEl.parentNode.nodeType == 1 && charEl.parentNode.tagName.toLowerCase == 'span') charEl = charEl.parentNode; else return; } // For IE patch if (charEl.parentNode.tagName.toLowerCase == 'a') charEl = charEl.parentNode; if (charEl.tagName.toLowerCase == 'a'){ charEl = charEl.parentNode; event.returnValue = false; } // End IE  if (charEl.nodeType != 1 || charEl.tagName.toLowerCase != 'span') return;

if ((' '+charEl.parentNode.className+' ').indexOf(' chargroup ') == -1){ // span interno? if ((' '+charEl.parentNode.parentNode.className+' ').indexOf(' chargroup ') == -1) return; else charEl = charEl.parentNode; }

var spans = charEl.getElementsByTagName('span'); if (spans.length < 2) insertTags(charInsert.getElementText(charEl), , ); else insertTags(charInsert.getElementText(spans[0]), charInsert.getElementText(spans[1]), ''); };

charInsert.getElementText = function(element){ if (element.textContent) return element.textContent; else if (element.innerText) return element.innerText; };

charInsert.eventTargetElement = function(event){ if (event.target) return event.target; else if(event.srcElement) //IE return event.srcElement; else // ?? return null; }

charInsert.addEvent = function(element, hookName, hookFunct) { if (element.addEventListener) element.addEventListener(hookName, hookFunct, false); else if (element.attachEvent) element.attachEvent('on' + hookName, hookFunct); }

To start this utility, the function charInsert.activaCaracteresEspeciales must be executed. You must have declared all the functions before of executing this function. When executed, it will find an element with the id attribute set as defined in charInsert.bindId (it could be changed) where initialize it.

In a wiki powered by MediaWiki it could be done putting the following instruction below of all of the utility's code:

addOnloadHook(charInsert.activaCaracteresEspeciales);

CSS
The interface appearance is customizable using Cascading Style Sheets (CSS). For example, to make the active characters an appearance of a keyboard, you can put this code in MediaWiki:Common.js, Special:Mypage/monobook.css or similar:

Note: If tou changed the charInsert.bindId variable, you must replace the identifier associated to the following CSS rules (in this case "#charinsert-block") to match your change.

padding: 2px; border: 1px solid #dfe6ff; background: #efefef; color: #000000; line-height: 1.8em; }
 * 1) charinsert-block {


 * 1) charinsert-block select { margin-right: 0.5em; }

padding: 0 2px; border: 1px solid #afafaf; background: #dddddd; cursor: pointer; white-space: nowrap; }
 * 1) charinsert-block .chargroup span {


 * 1) charinsert-block .chargroup > span:hover { background: #ffffff; }

background: transparent; border: none; }
 * 1) charinsert-block .chargroup span span {

text-decoration: none; color: black; }
 * 1) charinsert-block .chargroup span a {

Pages
This utility will appear in pages where a div which has the same id</tt> attribute defined in charInsert.bindId</tt>.

Technically, it has no need to contain nothing —it could be a div without content. It's not recommended to put nothing in it except if you want to include a group of characters in the HTML code. The div usually must be placed in MediaWiki:Edittools.

Note: Until the rest of the explanation, the id</tt> attribute of the div</tt> container will have their value set as charinsert-block</tt> as an example, and must be defined in charInsert.bindId</tt>. To use other value you must change both, the id attribute in the HTML, in the JavaScript property and in the CSS style rules that could have been defined for that id.

Example without any group defined in the HTML, loading only the characters defined in charInsert.groups</tt> (refer to Basic customization for further information):

To preload a group of characters in the HTML of he page, that will be avaliable although JavaScript is disabled —in this case the characters would appear but there wouldn't be any action associated to mouse clicks:

<pre style="overflow:auto"> ~ –  —  …   «  »

The behavior would be the following:

Each div</tt> element with class attribute set to chargroup</tt> inside an other div</tt> of id defined in charInsert.groups</tt> would be a character group. The group's name would be defined by it's title</tt> attribute. When more than one group (defined in HTML and JavaScript) a select input will appear to show only one of the groups.

Each span</tt> element inside the group will insert its text content inside the edit box when clicked. If there are 2 nested span</tt> in the same span</tt> element, the contents of the first element would be inserted before the caret position or text selection, and the second's content after the caret position or text selection.

Per-user installation
(translation in progress)

<!--

Instalación por usuario
El código funciona también si se instala a nivel de usuario, es decir, no disponible para toda la wiki sino sólo para el usuario que se lo quiera instalar en su Monobook.js (o similar).

Para ello el código será el mismo, pero no se tiene acceso a MediaWiki:Edittools por lo que, o existe ya en esa página un div con el id definido en charInsert.groups</tt>, o habrá que agregarlo por JavaScript antes de que se cargue la utilidad. Si es el caso, habrá que poner esto en el código antes del addOnloadHook(charInsert.activaCaracteresEspeciales);</tt>, o adaptarlo según gustos:

Para agregarlo justo debajo de cualquier textarea:

addOnloadHook(function{ var txts = document.getElementsByTagName('textarea');  if (txts.length < 1) return;  var div = document.createElement('div');  div.id = charInsert.bindId; // Especificamos el mismo id definido en charInsert.bindId  txts[0].parentNode.insertBefore(div, txts); });

Ejemplo de código personalizado por usuario: User:Ciencia Al Poder/monobook.js

Presentación
La presentación de los caracteres se puede personalizar usando reglas de estilo CSS. Sólo se fuerza por JavaScript la visibilidad de los grupos, permitiendo una gran personalización.

Si se utilizan grupos en el propio HTML, se pueden establecer propiedades de estilos en línea. Por ejemplo, ocultar los grupos de caracteres, para que no aparezcan hasta que se activen por JavaScript, o evitará que se muestren si el JavaScript no está activado.

Texto personalizado
Para agregar grupos de caracteres personalizados por JavaScript (nótese que no solo se pueden agregar caracteres, sino cualquier pedazo de texto) hay que agregar al objeto <tt>charInsert.groups</tt> nuevas propiedades. El nombre de la propiedad será el nombre del grupo de caracteres que aparecerá en el cuadro de selección (visible sólo si hay más de un grupo definido). El valor de la propiedad deberá ser un Array de strings. Cada elemento de convertirá en un elemento sobre el que se podrá hacer clic en él.

Los elementos del array que a su vez también sean otro array convertirán el elemento en complejo, y se insertará el primer elemento del array anidado antes de la posición del cursor, mientras que el segundo elemento del array anidado después del cursor o selección.

charInsert.groups[ "Nombre del grupo" ] = [ 'as', 'df' , [ '«' , '»' ] ];


 * Se pueden insertar tantos grupos como se quieran.
 * El nombre del grupo es el que aparecerá en el cuadro de selección de grupos (si hay más de uno disponible). Puede contener espacios. Si se definen más de uno con el mismo nombre, el último definido sobrescribirá al anterior.
 * Los elementos simples del array serán cadenas de texto que se insertarán en la posición del cursor.
 * Los elementos complejos del array (otro array dentro del array principal) formarán una única región de texto sobre la que interactuar, pero se insertará la primera parte del texto antes de la posición del cursor y la segunda después. Si hay más elementos en el sub-array serán ignorados.

De la misma forma se pueden agregar elementos en el propio HTML de la página, insertando en el elemento <tt>div</tt> de propiedad <tt>id</tt> definida en la variable <tt>charInsert.bindId</tt> uno o más elementos <tt>div</tt> de propiedad <tt>class</tt> <tt>chargroup</tt>. En su interior debe haber un elemento <tt>span</tt> que será cada región de texto que se insertará. Si en su interior hay dos elementos <tt>span</tt>, éstos se insertarán a ambos lados de la selección, o del cursor si no hay nada seleccionado:

<div class="chargroup" title=" Nombre del grupo "> as    df        «  »


 * <tt>  </tt>: (El id especificado también en la variable <tt>charInsert.bindId</tt>) Lugar donde aparecerán la selección de caracteres de esta utilidad. Sólo puede haber uno en la página. Si no existe este elemento, no aparecerá la utilidad. Para que aparezca en un <tt>div</tt> con otro valor de <tt>id</tt> hay que cambiarlo en todos los lugares donde aparece en el código.
 * <tt> <div class="chargroup" title=" Nombre del grupo ">  </tt>: Grupos de caracteres. Tal como ya se ha explicado, sólo aparecerá el grupo seleccionado. El resto permanecerá oculto. Se podrá seleccionar uno u otro a través de un cuadro de selección. El título de cada selección vendrá definido por el atributo <tt>title</tt> de cada <tt>div</tt>. Puede haber más de un grupo.
 * Los elementos <tt>    </tt> que contengan sólo texto en su interior será el texto que se insertará en la posición del cursor. Nota: Para insertar como texto elementos reconocibles por el software de MediaWiki sin que sean interpretados como tal, usa el elemento <tt>&lt;nowiki&gt;</tt> o utiliza referencias de carácter (como <tt>&amp;lt;</tt> para el carácter &lt;, etc).
 * Si dentro de un elemento <tt>span</tt> hay dos elementos <tt> span </tt>, el elemento será único pero al pulsar sobre él se insertará el contenido del primer <tt>span</tt> antes de la selección y el contenido del segundo después.

Nota importante: Al insertar los elementos <tt>   </tt> en el HTML hay que hacerlo todo en una única línea, sin saltos de línea, ya que por alguna razón el software MediaWiki insertará automáticamente el contenido dentro de un elemento <tt>    </tt> y causará un funcionamiento incorrecto.

Por ejemplo:

<pre style="overflow:auto;"> charInsert.groups["MediaWiki"] = [ '~', [], [,], ['#REDIRECT ',], [' '], ' ', ''];

equivaldría a colocar en MediaWiki:Edittools lo siguiente:

<pre style="overflow:auto;"> ~            #REDIRECT

Nótese que es mucho más sencillo agregar grupos por JavaScript que por HTML, además de incluir menos código. Además, el código en MediaWiki:Edittools se carga cada vez que se edita una página, mientras que el código JavaScript hace uso de la caché del navegador y se carga sólo una vez hasta que se refresca o vacía la caché.

Deshabilitar cookies
En el caso de que haya más de un grupo, aparecerá un cuadro de selección para seleccionar uno de ellos, ocultando el resto. Al seleccionar uno de ellos se guardará en una cookie de sesión el valor del grupo seleccionado, para que al recargar la página se cargue el último grupo seleccionado. Esto ocurrirá sólo si las cookies están habilitadas en el navegador. La cookie se borrará al cerrar la ventana del navegador.

Si tiene configurado el navegador para que le pregunte si quiere guardar cada cookie y/o quiere deshabilitar este comportamiento, puede colocar lo siguiente en el código JavaScript:

charInsert.disableCookie = true;

De esta forma no se escribirán cookies en el navegador al seleccionar un grupo, pero tampoco se leerán al cargar la utilidad.

Usar funciones propias
Es posible que hayas personalizado tu JavaScript o el de la Wiki que administres. Si en la wiki ya hay funciones que realizan lo mismo, puedes sustituir las que aquí se incluyen por una referencia a las que ya haya definidas. Por ejemplo, es posible que hayas definido funciones para que te devuelvan el texto de un elemento, o que devuelvan el elemento que inició un evento. En ese caso sólo tienes que reemplazar las funciones repetidas asignando una referencia a la función:

charInsert.eventTargetElement = window.eventTargetElement;

charInsert.addEvent = window.addEvent;

Comprobar esta utilidad
WikiDex tiene instalada esta utilidad para toda la wiki. Puedes probar su funcionamiento editando la Zona de pruebas.

El código está dividido en varias partes: w:c:es.pokemon:MediaWiki:Edittools, w:c:es.pokemon:MediaWiki:Common.js, w:c:es.pokemon:MediaWiki:Edit.js, w:c:es.pokemon:MediaWiki:Common.css.

Regstro de cambios

 * Versión 1.0
 * Primera versión


 * Versión 1.1
 * Arreglado bug al obtener el grupo guardado en la cookie
 * Nueva variable <tt>charInsert.bindId</tt> donde poder especificar de forma centralizada el ID donde activar la uilidad.

-->

es:User:Ciencia Al Poder/CharInsert