Análisis del código fuente de FCKEditor (I) Análisis de anotación china de fckeditor.js ha estado estudiando el código fuente de FCKEditor en los últimos días (FCKEditor es un editor web con una amplia gama de aplicaciones en la red). Necesito agradecer a NiLeaderBlog por su dura traducción.
Busqué casi todo Internet, y parece que he explicado mucho sobre el archivo fckconfig.js, pero la información sobre el archivo FCK central de fckeditor.js es casi 0.
Por lo tanto, pasé un día entero apretando la pasta de dientes para comentar sobre el archivo central fckeditor.js, fckeditor.js, como referencia de los internautas que también aprenden fckeditor.
Dado que el nivel del autor es limitado, aquí, señale los puntos inapropiados en mis comentarios para evitar engañar a otros. Gracias.
Se recomienda copiarlo a su IDE o
Nota: Este artículo se basa en FCKEditor2.6.5
Para obtener más información autorizada, consulte la Guía de desarrolladores oficiales de FCK
La copia del código es la siguiente:
/**
*
**********Derechos de autor***************
*-------- Anotado por NiLeader ----
*---- Versión 1.00 2009-10-18 ----
*---- Una vez copiado, marcado http://www.nileader.cn
*
* Clase FCKEditor anotada por NiLeader
* @param {object} InstanceName El nombre único del editor (equivalente a ID) es un parámetro no salvado.
* Ancho, altura, barra de herramientas, valor son todos los parámetros opcionales
*/
var fcKEditor = function (instancename, ancho, altura, barra de herramientas, valor)
{
// Propiedades básicas del editor Nota: Estas cosas tienen prioridad sobre la configuración en fckconfig.js
this.instanceName = InstanceName; // El nombre único del editor (equivalente a ID) (¡debe tener!)
this.width = ancho || '100%'; // El ancho es 100% por defecto
this.Height = altura || '200'; // El ancho es 200 por defecto
this.ToolBarSet = Tool Barset || 'Default'; // El nombre de conjunto de herramientas, el valor predeterminado es predeterminado
this.value = valor || ''; // Inicializar el código HTML del editor, el valor predeterminado está vacío
// La ruta raíz predeterminada cuando se inicializa el editor es escribir FCK. Todas las rutas utilizadas están predeterminadas a / fcKEditor / desde el directorio fckeditor.basepath.
this.basepath = fckeditor.basepath;
this.eckbrowser = true; // si verificar la compatibilidad del navegador antes de mostrar el editor, el valor predeterminado es verdadero
this.displayErrors = true; // Si se muestra con errores, el valor predeterminado es verdadero
this.config = new Object ();
// Eventos
this.onerror = nulo; // función (fuente, Errornumber, Errordescription) Función de manejo de errores personalizados
}
Fckeditor.basePath = '/fckeditor/'; // Directorio raíz predeterminado de FCK
Fckeditor.Minheight = 200; // Los límites de altura y ancho
FcKEditor.MinWidth = 750;
Fckeditor.prototype.version = '2.6.5'; // número de versión
Fckeditor.prototype.versionBuild = '23959';
/**
* Llame a CreateHtml () para generar el código HTML del editor y genere el editor en la página
*/
Fckeditor.prototype.create = function ()
{
// llamando al método createhtml ()
document.write (this.createhtml ());
}
/**
* @return shtml código html utilizado para generar el editor
*/
Fckeditor.prototype.createhtml = function ()
{
// Compruebe si hay un nombre de instance, no se generará ningún código HTML
if (! this.instancename || this.instancename.length == 0)
{
this._throwerror (701, 'debe especificar un nombre de instancia');
devolver '' ;
}
// Valor de retorno de la función
var shtml = '';
/*
* Cuando el navegador del usuario se encuentra con varios navegadores preestablecidos,
* Genere un cuadro de texto con id = this.instanceName name = this.instanceName, el almacenamiento de contenido de facto
*/
if (! this.checkbrowser || this._isCompatibleBrowser ())
{
// Pon esta entrada después de que se escape el valor inicial de FCK
shtml + = '<input type = Hidden id =' + this.instancename + 'name =' + this.instanceName + 'value =' + this._htmlencode (this.value) + 'style = display: none style = display: none />';
// Generar una entrada oculta para colocar los contenidos en este.config
shtml += this._getConfightMl ();
// código para generar el iframe del editor
shtml += this._getiframehtml ();
}
/**
* Si el navegador del usuario no es compatible con los navegadores FCK predeterminados
* Solo se pueden encontrar texturas tradicionales
*/
demás
{
var swidth = this.width.ToString (). indexOf ('%')> 0? this.width: this.width + 'px';
var sheight = this.height.toString (). indexOf ('%')> 0? this.Height: this.Height + 'Px';
shtml + = '<textarea name =' + this.instancename +
'filas = 4 cols = 40 estilo = ancho:' + swidth +
'; altura:' + sheight;
if (this.tabindex)
shtml + = 'tabindex =' + this.tabindex;
shtml += '>' +
this._htmlencode (this.value) +
'<// textarea>';
}
devolver shtml;
}
/**
* Use el editor para reemplazar el cuadro de texto correspondiente
*/
Fckeditor.prototype.replacetextarea = function ()
{
// Si ya tiene la etiqueta id = this.instanceName ___ marco, regresa directamente
if (document.getElementById (this.instanceName + '___frame'))
devolver ;
// Cuando el navegador del usuario se encuentra con varios navegadores preestablecidos
if (! this.checkbrowser || this._isCompatibleBrowser ())
{
// Debemos verificar los elementos en primer lugar usando la ID y luego el nombre.
// Obtener la etiqueta HTML de id = this.instancename
var oTexTarea = document.getElementById (this.instanceName);
// Obtener todas las etiquetas de nombre = this.instanceName
var colelementsByName = document.getElementsByName (this.instanceName);
var i = 0;
/*
* Teniendo en cuenta que el nombramiento de la etiqueta HTML del usuario no está estandarizado, el siguiente registro se realiza para determinar que el autor se refiere al usuario usando name = this.instanceName en la etiqueta TextAREA.
* Name = this.instanceName también se usa en otras etiquetas en la misma página
*/
Mientras (oTextarea || i == 0)
{
// Viaje hasta que la etiqueta TextAREA de nombre = this.instancename se encuentra y asigna a OtexTarea
if (oTextArea && oTexTarea.tagname.tolowercase () == 'textARea')
romper;
oTextArea = ColelementsByName [i ++];
}
// Si no hay etiqueta con ID o nombre de esto.
if (! oTextarea)
{
alerta ('Error: la textura con id o nombre establecido en' + this.instancename + 'no se encontró');
devolver ;
}
/*
* Después de confirmar que la etiqueta TextAREA con name = this.instanceName existe, asignarle el código del editor
*/
oTexTarea.style.display = 'Ninguno';
// Si el orden de la tecla TAB se define en la página para tales etiquetas TextAREA, asignarlo a este.tabindex para su uso posterior
if (oTextarea.tabindex)
this.tabindex = oTexTarea.tabindex;
this._insertttmlbefore (this._getConfightMl (), oTextArea);
this._insertttmlbefore (this._getiframehtml (), oTextArea);
}
}
/**
* Inserte el código HTML frente a la etiqueta de la página especificada
* @param {objeto} código HTML que se insertará
* @param {objeto} etiqueta de página especificada (objeto)
*/
Fckeditor.prototype._inserthtmlbefore = function (html, elemento)
{
if (element.insertadjacenthtml) // es decir, el método privado insertadjacenthtml
elemento.insertadjacenthtml ('antes de Begin', html);
más // navegador no II
{
var naranja = document.createrange ();
naranja.setStartbefore (elemento);
var ofRagment = Orange.CreateContextualFragment (html);
elemento
}
}
/*
* Genere un dominio oculto editando este.config [].
* Por ejemplo:
* this.config ['nileader'] = 1104, this.config ['Leaderni'] = nichao ...
* Entonces, Sconfig =… & nileader = 1104 & Leaderni = nichao ...
* Por supuesto, al final, la función de Sconfig se convertirá en un porcentaje de codificación por la función Codeuricomponent y se pondrá en una entrada oculta
*/
Fckeditor.prototype._getconfightml = function ()
{
var sconfig = '';
para (var o en this.config)
{
if (sconfig.length> 0) sconfig += '&';
// La función de EncodeuricOponent se convierte en codificación porcentual
sconfig + = encodeuricOponent (o) + '=' + encodeuricomponent (this.config [o]);
}
return '<input type = hidden id =' + this.instancename + '___config value =' + sconfig + 'style = display: none style = display: none />';
}
/*
* Genere el HTML del iframe. Aquí implica la determinación de SRC
*/
Fckeditor.prototype._getiframehtml = function ()
{
var sfile = 'fckeditor.html';
// Caso especial, la ventana donde se encuentra fckedito no está integrada en el navegador
intentar
{
if ((/fckSource = true/i) .test (window.top.location.search)))
sfile = 'fckeditor.original.html';
}
Catch (E) { /* Ignore esta excepción. Muchas veces, la ventana donde se encuentra Fckedito está incrustada en el navegador. */}
/*
* Una cosa a tener en cuenta aquí:
* Cómo funciona iframe: cuando el iframe está en estado editable, la página donde realmente se edita SRC
* Aquí hay un Slink para ponerlo en la etiqueta de iframe
*/
// Slink es esta página de facto, que comienza desde el directorio raíz de FCK, por ejemplo, SLINK =/fcKEditor/editor/fckeditor.html? Instancename = nileader & toolbar = nileadersbar
var slink = this.basepath + 'editor/' + sfile + '? InstanceName =' + codeDoRponent (this.instanceName);
if (this.ToolBarset)
Slink + = '& Tool Bar =' + this.ToolBarSet;
// Generar un código HTML real para editar iframer, por supuesto, poner src = slink
var html = '<iframe id =' + this.instancename +
'___Frame src =' + Slink +
'src =' + slink +
'width =' + this.width +
'altura =' + this.Height;
// Si se establece el orden de transversal usando la tecla TAB, asigna al iframe
if (this.tabindex)
html + = 'tabindex =' + this.tabindex;
html += 'frameBorDer = 0 scrolling = no> </iframe>';
devolver html;
}
/*
* Verifique si el Bowser del usuario es el valor predeterminado de FCK
* Este método es solo una empresa FK persiguiendo oo, sin sentido
*/
Fckeditor.prototype._isCompatibleBrowser = function ()
{
return fckeditor_isCompatibleBrowser ();
}
/**
* Error lanzado
* @param {objeto} Número de error de Errornumber
* @param {object} ErrorDescription Error Descripción general
*/
Fckeditor.prototype._throwerror = function (Errornumber, Errordescription)
{
this.errornumber = Errornumber;
this.errordescription = Errordescription;
// Si se muestra con errores, el valor predeterminado es verdadero
if (this.displayErrors)
{// Imprima el número de error y la descripción general del error
document.write ('<div style = color: #ff0000 style = color: #ff0000>');
document.write ('[FCKEditor Error' + this.errornumber + ':' + this.errordescription + ']');
document.write ('</div>');
}
// onError Si la función de manejo de errores se personaliza, si se define, será manejado por ella
if (typeof (this.onerror) == 'function')
this.
}
/**
* Texto de escape
* @param {objeto} texto para ser escapado
* @return texto de cadena después de escapar
*/
Fckeditor.prototype._htmlencode = function (texto)
{
if (typeof (text)! = string)
text = text.ToString ();
// sustituir a todos & <> en la cadena con los caracteres de escape correspondientes
text = text.replace (
/&/g, &). reemplazar (
// g,).
/</g, <). Reemplazar (
/>/g,>);
Texto de devolución;
}
;(función()
{
// Asigna el elemento TextAREA en la página a la variable del editor
var textareAteEditor = function (textarea)
{
Var editor = new FCKEditor (TextAea.name);
editor.width = Math.max (TextAea.OffSetWidth, fckeditor.minwidth);
editor.Height = Math.max (TextAea.OffSetheight, fckeditor.minheight);
Editor de regreso;
}
/**
* Reemplace todos los elementos <xtexarea> disponibles en el documento con FCKEditor
* instancias.
*
* // Reemplazar todos los elementos <TextArea> en la página.
* Fckeditor.replaceAllTextAleas ();
*
* // Reemplazar todos los elementos <TextARea class = myClassName> en la página.
* Fckeditor.replaceAlltexTareas ('myClassName');
*
* // Reemplaza selectivamente los elementos <xtexarea>, basados en afirmaciones personalizadas.
* Fckeditor.replaceAllTextAleas (function (textarea, editor)
* {
* // código personalizado para evaluar el reemplazo, devolviendo falso si
* // no debe hacerse.
* // también pasa el parámetro del editor, por lo que el desarrollador puede
* // Personaliza la instancia.
*});
*/
Fckeditor.replaceAllTextAleas = function ()
{
// Obtener todos los elementos Textarea
var textareas = document.getElementsByTagName ('textarea');
para (var i = 0; i <textareas.length; i ++)
{
VAR Editor = nulo;
var textArea = textEase [i];
var name = textarea.name;
// El atributo de nombre debe existir.
if (! name || name.length == 0)
continuar ;
if (typeof argumentos [0] == 'cadena')
{
// El nombre de la clase TextARea podría pasar como función
// Parámetro.
var classRegex = new Regexp ('(?:^|)' + argumentos [0] + '(?: $ |)');
if (! classegex.test (textARea.classname))
continuar ;
}
else if (typeof argumentos [0] == 'función')
{
// Se podría pasar una función de afirmación como parámetro de función.
// Debe devolver explícitamente falso para ignorar un específico <ExteAea>.
editor = textAreatoEditor (TextAea);
if (argumentos [0] (textAea, editor) === Falso)
continuar ;
}
if (! editor)
editor = textAreatoEditor (TextAea);
editor.replacExtexTarea ();
}
}
}) ();
/**
* Detectar la compatibilidad del navegador
* Uso de alguna información Sagent devuelta por el objeto Navigator, determina que el navegador devuelve información, incluido el nombre de código del navegador, el nombre del navegador, el idioma de la versión del navegador y otra información y minúsculas.
* Por ejemplo:
* Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322)
*
* Al juzgar el navegador IE, se agrega la compilación condicional compatible después de usar IE4.0.
* Dado que solo es compatible con IE, esta propiedad no es compatible con los navegadores estándar W3C. Por lo tanto, el IE se juzga adecuadamente utilizando esta característica
*/
función fckeditor_isCompatibleBrowser ()
{
var sagent = navigator.useragent.tolowercase ();
// El navegador actual es Internet Explorer 5.5+
// Use la compilación condicional para juzgar IE en IE,/*@cc_on!@*/False ==! falso == Verdadero,
// Si es un navegador no II, ignóralo,/*@cc_on!@*/False == False
if ( /*@cc_on!@* /false && sagent.indexof (mac) == -1) // no Apple Mac OS
{
var sbrowserversion = navigator.appversion.match (/msie (./..)/)[1];
return (sbrowserversion> = 5.5);
}
// gecko (Opera 9 intenta comportarse como gecko en este punto).
// Detección de si es un navegador Opera 9
if (navigator.product == gecko && navigator.productsub> = 20030210 &&! (typeof (opera) == 'object' && ópera.posterror)))
devolver verdadero;
// ópera 9.50+
if (window.opera && window.opora.version && parsefloat (window.opera.version ())> = 9.5)
devolver verdadero;
// Adobe Air
// verificar antes de Safari porque Air tiene el editor de texto rico en Webkit
// Características de Safari 3.0.4, pero la versión informada es 420.
if (sagent.indexof ('Adobeair/')! = -1)
return (sagent.match (/AdoBeair // (/d+)/) [1]> = 1); // La construcción debe ser al menos V1
// Safari 3+
if (sagent.indexof ('AppleWebkit/')! = -1)
return (sagent.match (/applewebkit // (/d+)/) [1]> = 522); // La construcción debe ser al menos 522 (V3)
devolver falso;
}