Анализ исходного кода Fckeditor (i) Анализ китайских аннотаций fckeditor.js изучал исходный код fckeditor в последние несколько дней (Fckeditor - веб -редактор с широким спектром приложений в сети). Мне нужно поблагодарить Nileaderblog за его жесткий перевод.
Я искал почти весь Интернет, и кажется, что я многое объяснил файл fckconfig.js, но информация о основном файле fck fckeditor.js почти 0.
Поэтому я потратил целый день, сжимая зубную пасту, чтобы прокомментировать файл основного файла fckeditor.js, fckeditor.js, для справки сети, которые также изучают fckeditor.
Учитывая, что уровень автора ограничен, здесь, пожалуйста, укажите на неподходящие пункты в моих комментариях, чтобы избежать вводящего в заблуждение других. Спасибо.
Рекомендуется скопировать его в свой IDE или
Примечание: эта статья основана на fckeditor2.6.5
Для получения более авторитетной информации, пожалуйста, обратитесь к руководству официальных разработчиков FCK
Кода -копия выглядит следующим образом:
/**
*
********** Авторские права ***************
*-------- Аннотирован Nileader ----
*---- Версия 1.00 2009-10-18 ----
*---- Однажды скопирован, помеченная http://www.nileader.cn
*
* Класс Fckeditor Аннотирован Nileader
* @param {object} instancename Уникальное имя редактора (эквивалентное ID) является неспасенным параметром.
* Ширина, высота, набор инструментов, значение - все дополнительные параметры
*/
var fckeditor = function (instanceName, ширина, высота, панель инструментов, значение)
{
// Основные свойства редактора Примечание. Эти вещи имеют приоритет над конфигурацией в fckconfig.js
this.InStancEname = InstancEname; // Уникальное имя редактора (эквивалентное ID) (должно быть!)
this.width = ширина || «100%»; // ширина по умолчанию составляет 100%
this.height = высота || '200'; // ширина по умолчанию составляет 200
this.toolbarset = наборы инструментов || 'По умолчанию'; // Имя набора инструментов, значение по умолчанию по умолчанию
this.value = value || ''; // Инициализировать код HTML редактора, значение по умолчанию пусто
// Путь корня по умолчанию, когда редактор инициализируется, - это написать FCK. Все используемые пути не выполняются / fckeditor / от каталога fckeditor.basepath.
this.basepath = fckeditor.basepath;
this.checkbrowser = true; // Чтобы проверить совместимость браузера перед отображением редактора, по умолчанию верно
this.displayerrors = true; //, отображается ли он с ошибками, по умолчанию верно
this.config = new Object ();
// События
this.onerror = null; // Функция (источник, Errornumber, Errordescription) Пользовательская функция обработки ошибок
}
Fckeditor.basepath = '/fckeditor/'; // Справочник по умолчанию FCK по умолчанию
Fckeditor.minheight = 200; // пределы высоты и ширины
Fckeditor.minwidth = 750;
Fckeditor.prototype.version = '2.6.5'; // номер версии
Fckeditor.prototype.versionbuild = '23959';
/**
* CALL CREATEHTML () для генерации HTML -кода редактора и вывода редактора на странице
*/
Fckeditor.prototype.create = function ()
{
// Вызов метода createhtml ()
document.write (this.createhtml ());
}
/**
* @return Shtml HTML -код, используемый для генерации редактора
*/
Fckeditor.prototype.createhtml = function ()
{
// Проверьте, есть ли имя инстакзала, HTML -код не будет
if (! this.instancename || this.instancename.length == 0)
{
this._throwerror (701, «Вы должны указать имя экземпляра. ');
возвращаться '' ;
}
// возвращаемое значение функции
var shtml = '';
/*
* Когда браузер пользователя встречает несколько заданных браузеров,
* Сгенерировать текстовое поле с id = this.instanceName name = this.instancename, де -факто хранилище контента
*/
if (! this.checkbrowser || this._iscompatiblebrowser ())
{
// Поместите этот вход после того, как начальное значение FCK ускользается
shtml + = '<input type = hidden id =' + this.instancename + 'name =' + this.instancename + 'value =' + this._htmlencode (this.value) + 'style = display: none style = display: none />';
// генерировать скрытый вход, чтобы поместить содержимое в этом.
shtml += this._getConfightml ();
// код для создания iframe редактора
shtml += this._getiframehtml ();
}
/**
* Если браузер пользователя не совместим с браузерами FCK по умолчанию
* Можно найти только традиционные текстовые мешки
*/
еще
{
var swidth = this.width.tostring (). Indexof ('%')> 0? this.width: this.width + 'px';
var sheute = this.height.tostring (). indexof ('%')> 0? this.height: this.height + 'px';
shtml + = '<textarea name =' + this.instancename +
'Rows = 4 Cols = 40 Style = ширина:' + swidth +
'; рост:' + heuett;
if (this.tabindex)
shtml + = 'tabindex =' + this.tabindex;
shtml += '>' +
this._htmlencode (this.value) +
'<// textarea>';
}
вернуть SHTML;
}
/**
* Используйте редактор, чтобы заменить соответствующее текстовое поле
*/
Fckeditor.prototype.replacetextarea = function ()
{
// Если у вас уже есть идентификатор тега = this.instanceName ___ кадр, верните напрямую
if (document.getElementbyId (this.InstancEname + '___frame'))
возвращаться ;
// Когда браузер пользователя встречает несколько заданных браузеров
if (! this.checkbrowser || this._iscompatiblebrowser ())
{
// Мы должны сначала проверить элементы, используя идентификатор, а затем имя.
// Получить HTML -тег ID = This.InstancEname
var otextarea = document.getElementById (this.InstancEname);
// Получить все теги имени = this.InstancEname
var collementsbyname = document.getElementsbyname (this.instancename);
var i = 0;
/*
* Учитывая, что именование HTML -тега пользователя не стандартизировано, сделана следующая запись, чтобы определить, что автор относится к пользователю, использующему name = this.instanceName в теге Textarea.
* Name = this.InStancEname также используется на других тегах на той же странице
*/
while (otextarea || i == 0)
{
// Путешествовать до тега Textarea of name = this.instancEname найдено и назначено Otextarea
if (otextarea && otextarea.tagname.tolowercase () == 'textarea')
перерыв;
otextarea = collementsbyname [i ++];
}
// Если нет тега с идентификатором или именем этого.
if (! Otextarea)
{
Alert ('error: TextAREA с идентификатором или именем, установленным' + this.InStancEname + 'не было найдено');
возвращаться ;
}
/*
* После подтверждения того, что тег Textarea с name = this.InstancEname существует, назначьте код редактора ему
*/
otextarea.style.display = 'none';
// Если порядок ключа вкладки определен на странице для таких тегов Textarea, назначьте его на это. Tabindex для дальнейшего использования
if (otextarea.tabindex)
this.tabindex = otextarea.tabindex;
this._inserthtmlbefore (this._getConfightml (), otextarea);
this._inserthtmlbefore (this._getiframehtml (), otextarea);
}
}
/**
* Вставьте код HTML перед указанной тегом страницы
* @param {object} html -код для вставки
* @param {Object} указанная тег страницы (Object)
*/
Fckeditor.prototype._inserthtmlbefore = function (html, element)
{
if (element.insertadjacenthtml) // т.е.
element.insertAdjacenthtml ('перед Begin', html);
else // браузер без эксплуатации
{
var Orange = Document.CreaterAnge ();
Orange.SetStartBefore (Element);
var ofragment = Orange.CreateContextualFragment (html);
element.parentnode.insertbefore (offagment, element);
}
}
/*
* Сгенерируйте скрытый домен, редактируя это. Config [].
* Например:
* this.config ['nileader'] = 1104, this.config ['aderni'] = nichao ...
* Тогда, sconfig =… & nileader = 1104 & adverni = nichao…
* Конечно, в конце концов, Sconfig будет преобразован в процентную кодировку функцией Encodeuricomponent и помещен в скрытый вход
*/
Fckeditor.prototype._getConfightml = function ()
{
var sconfig = '';
для (var o в этом. Config)
{
if (sconfig.length> 0) sconfig += '&';
// функция Encodeuricomponent преобразуется в процентное кодирование
sconfig + = encodeuricomponent (o) + '=' + encodeuricomponent (this.config [o]);
}
return '<<input type = hidden id =' + this.instancename + '___config value =' + sconfig + 'style = display: none style = display: none />';
}
/*
* Сгенерируйте HTML Iframe. Здесь он включает в себя определение SRC
*/
Fckeditor.prototype._getiframehtml = function ()
{
var sfile = 'fckeditor.html';
// Специальный случай, окно, в котором находится Fckedito, не встроено в браузер
пытаться
{
if ((/fcksource = true/i) .test (window.top.location.search))
sfile = 'fckeditor.original.html';
}
поймать (e) { /* Игнорировать это исключение. Много раз окно, в котором находится Fckedito, встроено в браузер. */}
/*
* Одна вещь, чтобы отметить здесь:
* Как работает iframe: когда iframe находится в редактируемом состоянии, страница, где SRC фактически отредактирована
* Вот Slink, чтобы положить его в тег iframe
*/
// slink - это фактическая страница, начиная с корневого каталога FCK, например, slink =/fckeditor/editor/fckeditor.html? instancename = nileader & toolbar = nileadersbar
var slink = this.basepath + 'editor/' + sfile + '? instancename =' + encodeuricomponent (this.instancename);
if (this.toolbarset)
slink + = '& toolbar =' + this.toolbarset;
// Сгенерировать реальный HTML -код для редактирования Iframer, конечно, положить src = slink
var html = '<iframe id =' + this.instancename +
'___Frame src =' + slink +
'src =' + slink +
'width =' + this.width +
'height =' + this.height;
// Если установлен порядок обхода с использованием клавиши TAB, назначьте его iframe
if (this.tabindex)
html + = 'tabindex =' + this.tabindex;
html += 'crameborder = 0 scrolling = no> </iframe>';
вернуть HTML;
}
/*
* Проверьте, является ли буузер пользователя по умолчанию FCK
* Этот метод просто FK Company, преследуя OO, бессмысленная
*/
Fckeditor.prototype._iscompatiblebrowser = function ()
{
return fckeditor_iscompatiblebrowser ();
}
/**
* Ошибка
* @param {object} номер ошибки Errornumber
* @param {Object} обзор ошибок ошибки
*/
Fckeditor.prototype._throwerror = function (errornumber, errordescription)
{
this.errornumber = errornumber;
this.errordescription = errordescription;
//, отображается ли он с ошибками, по умолчанию верно
if (this.displayerrors)
{// распечатать номер ошибки и обзор ошибок
document.write ('<<div style = color: #ff0000 style = color: #ff0000>');
document.write ('[[fckeditor error' + this.errornumber + ':' + this.errordescription + ']');
document.write ('</div>');
}
// onerror, настраивается ли функция обработки ошибок, если она будет определена, она будет обрабатываться им.
if (typeof (this.onerror) == 'function')
this.onerror (это, Errornumber, Errordescription);
}
/**
* Побег из текста
* @param {Object} текст, который должен быть сбежал
* @return строка текст после побега
*/
Fckeditor.prototype._htmlencode = function (текст)
{
if (typeof (text)! = String)
text = text.tostring ();
// заменить все и <> в строке соответствующими экологичными символами
text = text.replace (
/&/g, &). Заменить (
// g,) .replace (
/</g, <). Заменить (
/>/g,>);
вернуть текст;
}
; (function ()
{
// назначить элемент Textarea на странице с переменной редактора
var textAreatoeditor = function (textarea)
{
var Editor = new fckeditor (textarea.name);
editor.width = math.max (textarea.offsetwidth, fckeditor.minwidth);
editor.height = math.max (textarea.offsetheight, fckeditor.minheight);
вернуть редактор;
}
/**
* Замените все элементы <textarea>, доступные в документе с fckeditor
* экземпляры.
*
* // Заменить все <textarea> элементы на странице.
* Fckeditor.replacealltextareas ();
*
* // Заменить все <textarea class = myclassname> элементы на странице.
* Fckeditor.replacealltextareas ('myclassname');
*
* // Селективно заменить <TextArea> Элементы, основанные на пользовательских утверждениях.
* Fckeditor.replacealltextareas (function (textarea, редактор)
* {
* // пользовательский код для оценки замены, возвращая false, если он
* // не должно быть сделано.
* // он также проходит параметр редактора, поэтому разработчик может
* // Настроить экземпляр.
*});
*/
Fckeditor.replacealltextareas = function ()
{
// Получить все элементы Textarea
var TextAreas = document.getElementsbytagname ('textarea');
для (var i = 0; i <textareas.length; i ++)
{
var Editor = null;
var textARea = textAreas [i];
var name = textarea.name;
// Имя атрибут должен существовать.
if (! Имя || name.length == 0)
продолжать ;
if (typeof Arguments [0] == 'String')
{
// имя класса Textarea может быть передано в качестве функции
// параметр.
var classregex = new Regexp ('(?:^|)' + аргументы [0] + '(?: $ |)');
if (! classregex.test (textarea.classname)))
продолжать ;
}
иначе if (typeof arguments [0] == 'function')
{
// Функция утверждения может быть передана в качестве параметра функции.
// он должен явно вернуть false, чтобы игнорировать конкретный <Textarea>.
editor = textAreatoeditor (textarea);
if (аргументы [0] (textarea, редактор) === false)
продолжать ;
}
if (! Редактор)
editor = textAreatoeditor (textarea);
editor.replacetextarea ();
}
}
}) ();
/**
* Обнаружение совместимости браузера
* Использование некоторой информации Sagent, возвращаемой объектом Navigator, он определяет, что браузер возвращает информацию, включая кодовое имя браузера, имя браузера, язык версии браузера и другую информацию и строчные.
* Например:
* Mozilla/4.0 (совместимо; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322)
*
* При оценке браузера, т.е., добавляется поддерживаемая условная компиляция после использования IE4.0.
* Поскольку он поддерживается только IE, это свойство не поддерживается в стандартных браузерах W3C. Следовательно, IE осуждается надлежащим образом с помощью этой функции
*/
function fckeditor_iscompatiblebrowser ()
{
var Sagent = navigator.UserAgent.tolowerCase ();
// текущий браузер - интернет -проводник 5.5+
// Используйте условную компиляцию, чтобы судить IE в IE,/*@CC_ON!@*/False ==! false == true,
// Если это браузер, не связанный с ИЕ, игнорируйте его,/*@cc_on!@*/False == false
if ( /*@cc_on!@* /false && sagent.indexof (mac) == -1) // не Apple Mac OS
{
var sbrowserVersion = navigator.appversion.match (/msie (./..)/)^];
return (sbrowserversion> = 5,5);
}
// гекко (Opera 9 пытается вести себя как геккону на данный момент).
// обнаружение, является ли это браузером Opera 9
if (navigator.product == gecko && navigator.productsub> = 20030210 &&! (typeof (opera) == 'Object' && opera.posterror))))
вернуть истину;
// Opera 9.50+
if (window.opera && window.opera.version && parsefloat (window.opera.version ())> = 9.5)
вернуть истину;
// Adobe Air
// проверено перед сафари, потому что у Air есть текстовый редактор богатого Webkit
// функции от Safari 3.0.4, но сообщаемая версия 420.
if (sagent.indexof ('adobeair/')! = -1)
return (sagent.match (/adobeair // (/d+)/) [1]> = 1); // сборка должна быть не менее v1
// Safari 3+
if (sagent.indexof ('applewebkit/')! = -1)
return (sagent.match (/applewebkit // (/d+)/) [1]> = 522); // сборка должна быть не менее 522 (v3)
вернуть ложь;
}