Доброго времени суток уважаемые хабровчане.
Активно пользуюсь уже несколько месяцев.
AngularJS в одном из рабочих проектов.
Я не буду петь «хвалебные песни» или превозносить эти рамки, потому что идеальных вещей не бывает (и, наверное, было бы очень скучно жить в мире с такими вещами, которые не оставляют возможности преодолевать свои недостатки своим «творчеством»).
»).
Скажу лишь несколько слов о результатах: идеология AngularJS очень хорошо справляется с организацией кода и предоставляет волшебный инструмент Directives. Кстати, недавно была заметка про CornerJS , в котором директивы вынесены в центр технологий, а на Google I/O в этом году проскочила новость о возможной поддержке пользовательские элементы (не просто теги, а сложные html-компоненты, встроенные в страницу).
На следующем этапе разработки встал вопрос об интеграции с продвинутым WYSIWYG-редактором и мой взгляд сразу упал на ckEditor , так как я уже несколько раз использовал его в проектах на базе DotNetNuke и впечатления были очень положительные (или, скажем по-другому: серьезных недостатков в компоненте обнаружено не было, а интеграция заняла считанные часы).
Умоляя Google помочь с магией интеграции, я получил несколько ссылок на Stackoverflow и другие частные блоги, где решение всех проблем — событие.
пастастате а директива в целом выглядит просто и доступно:
Но после очередного мэйлстоуна и деплоя заказчик стал замечать, что иногда редактируемый текст не полностью сохраняется или компонент даже вылетает с Access Violation, в случае с ранними версиями InternetExplorer(< 9).app.directive('ckEditor', [function () { return { require: 'ЭngModel', link: function ($scope, elm, attr, ngModel) { var ck = CKEDITOR.replace(elm[0]); ck.on('pasteState', function () { $scope.$apply(function () { ngModel.$setViewValue(ck.getData()); }); }); ngModel.$render = function (value) { ck.setData(ngModel.$modelValue); }; } }; }]);
The problem was reproduced, ideal conditions were obtained and I went to look for a solution to the problem. Перечитав еще раз документацию и поковыряв страницу для общей картины, я пришел к выводу, что это событие прекрасно работает с клавиатурой, но полностью игнорирует вставку элементов (будь то текст, картинки и т.п.
) из включенных плагинов.
Сразу было решено искать новое мероприятие, носившее более глобальный характер.
Но результаты поиска привели к этому «неправославному» метод , который к тому же является еще и плагином (а это чревато миграцией или обновлением самого ckEditor).
Поэтому было решено обновить версию редактора до последней доступной (CKEditor 4.2.1 на тот момент), рискуя стабильностью и получая магическое событие.
изменять на уровне нативного API (возможно, они просто интегрировали вышеупомянутый плагин в ядро; я, честно говоря, не следил за историей).
Замена события на изменение помогла решить проблему с сохранением измененного контента, но не решила проблему с нарушением прав доступа.
Наученный горьким опытом неожиданно возникнуть окна для IE < 9 (IE splits the execution of different windows into different threads with a complete reset of cookies, etc.) I came to the conclusion that the problem is in the iframe component and the sequence of creating and accessing it inside ckEditor itself, as well as the life cycle объем в AngularJS. Проблема связана с тем, что метод CKEDITOR.replace(.
) в старом IE работает асинхронно и «освобождая» контекст выполнения AngularJS пытается привязать модель и вызвать setData , который пытается получить доступ к iframe, который еще не готов, что вызывает нарушение прав доступа.
Ничего «лучше» или «надёжнее», чем очередь, я придумать не смог, поэтому в результате получился следующий код директивы: app.directive('ckEditor', [function () {
return {
require: 'ЭngModel',
restrict: 'C',
link: function (scope, elm, attr, model) {
var isReady = false;
var data = [];
var ck = CKEDITOR.replace(elm[0]);
function setData() {
if (!data.length) { return; }
var d = data.splice(0, 1);
ck.setData(d[0] || '<span></span>', function () {
setData();
isReady = true;
});
}
ck.on('instanceReady', function (e) {
if (model) { setData(); }
});
elm.bind('$destroy', function () {
ck.destroy(false);
});
if (model) {
ck.on('change', function () {
scope.$apply(function () {
var data = ck.getData();
if (data == '<span></span>') {
data = null;
}
model.$setViewValue(data);
});
});
model.$render = function (value) {
if (model.$viewValue === undefined) {
model.$setViewValue(null);
model.$viewValue = null;
}
data.push(model.$viewValue);
if (isReady) {
isReady = false;
setData();
}
};
}
}
};
}]);
В коде есть неоднозначные моменты, связанные со значениями очереди и model.$viewValue (в частности, это были попытки бороться с зависанием компонентов в модальных диалогах, что решалось патчем модального компонента twitter bootstrap, но это уже другая история ).
Также я не до конца раскрыл моменты, связанные с setData(.
,callback), который по сути является одним из механизмов синхронизации, но мне кажется, что в этом контексте код выглядит информативно и будет заменять слова.
Выслушаю предложения и критику по поводу данного подхода.
P.S. Рабочий пример того, что я получил http://jsfiddle.net/jWANb/2/ Рабочий пример того, что рекомендуют в Интернете http://jsfiddle.net/fvApg/1/ Попробуйте вставить изображение во второй пример и посмотрите на «результат html».
Будет ясно, что контекст не изменился.
Теги: #angularjs #CKEditor #WYSIWYG #разработка веб-сайтов #JavaScript #angular
-
Huginn: Простая Платформа Интеграции
19 Oct, 24 -
Серебряная Пуля Для Кремлевского Демона
19 Oct, 24