CKEditor跟jQuery UI Dialog的結合
身為一個堪用的網路工程師
不可能不知道CKEditor跟jQuery Dialog這兩大利器
強大, 簡單, 好用到一個不行
雖然說CKEditor有點肥大
不過還是強大到可以忽略掉他的臃腫了
像我這種半調子的工程師基本上是寫不出來的 orz
本來想厚臉皮介紹一下這兩個的使用心得
後來想了一想
網路上的資源多到恐怖 相關的文章快滿出來
哪差我這一兩篇
這篇就拿來分享一下當時想把CKEditor放進jQuery Dialog遇到的一些瓶頸
在開始之前先貼上這兩個元件的官方網頁
1. jQuery UI - http://jqueryui.com/
2. CKEditor - http://ckeditor.com/
首先要先介紹一個CKEditor本身對jQuery的支援
在不知道哪一版, CKEditor檔案包裡面多了一個檔案 ckeditor\adapters\jquery.js
網頁中同時匯入這個檔案, 就可以使用jQuery存取CKEditor的一些屬性
例如說初始化 $('[selector]').ckeditor();
就可以把指定的dom轉成ckediotr了
我個人是覺得比原本的宣告方式直覺又明確的多了啦
回歸問題的重點, CKEditor放在Dialog的時候, 會互相衝突而沒辦法好好運作
尤其是在設定dialog({modal:true})的時候
會發現CKEditor連點都不能點
要討論背後的機制跟發生的原因太麻煩, 簡單來說UI套上去, 我們的html就加上了他們的程式邏輯
例如搬到form外面
改成絕對位置等等
因此兩套ui就會有衝突的可能
===================================================================================================================
最簡單的解法, 利用dialog所提供的兩個屬性
1. open – 在dialog打開的時候呼叫的function
2. close – 在dialog關閉的時候呼叫的function
至於要怎麼使用
$(function(){
$('#dialog').dialog({
open: function () {
$(this).find('textarea').ckeditor();
},
close: function () {
$(this).find('textarea').each(function(){
$(this).ckeditorGet().destroy();
});
}
});
});
簡單說明程式邏輯如下
dialog在open跟close的時候會把container的dom用this傳進去
因此我們可以去找出container下面的textarea把他轉成ckeditor ( 注意, 此處為了方便直接找出全部的textarea, 實際在使用的時候可以自己在修改[selector])
而在Close的時候把textarea的ckeditor給destroy掉
而這樣ckeditor的生命週期就會在dialog之間, 而不會衝突
至於詳細點可以看到open的時候可以直接接ckeditor()
但是close的時候卻要用each去一個一個destroy
這個原因牽扯到ckeditor內部套用$.fn機制的回傳型別, 因此一個可以直接串接一個不行
這算是題外話了
===================================================================================================================
而在用下去會發現另外一個問題
CKEditor可以用歸可以用, 但是在dialog modal的情況下, 點選超連結等CKEditor本身的對話方塊
會發現連點都不能點
基本上這又是兩個ui另外一個衝突的地方
而CKEditor少掉了那些好用的插入超連結等功能, 基本上等於半殘
當時為了找這個的解法找得好辛苦 = =
就當成留做筆記放在這邊
在程式中加上這段
/*修正 dialog modal, ckeditor的dialog會失去作用的問題*/
$.extend($.ui.dialog.overlay, { create: function (dialog) {
if (this.instances.length === 0) {
// prevent use of anchors and inputs
// we use a setTimeout in case the overlay is created from an
// event that we're going to be cancelling (see #2804)
setTimeout(function () {
// handle $(el).dialog().dialog('close') (see #4065)
if ($.ui.dialog.overlay.instances.length) {
$(document).bind($.ui.dialog.overlay.events, function (event) {
var parentDialog = $(event.target).parents('.ui-dialog');
if (parentDialog.length > 0) {
var parentDialogZIndex = parentDialog.css('zIndex') || 0;
return parentDialogZIndex > $.ui.dialog.overlay.maxZ;
}
var aboveOverlay = false;
$(event.target).parents().each(function () {
var currentZ = $(this).css('zIndex') || 0;
if (currentZ > $.ui.dialog.overlay.maxZ) {
aboveOverlay = true;
return;
}
});
return aboveOverlay;
});
}
}, 1);
// allow closing by pressing the escape key
$(document).bind('keydown.dialog-overlay', function (event) {
(dialog.options.closeOnEscape && event.keyCode
&& event.keyCode == $.ui.keyCode.ESCAPE && dialog.close(event));
});
// handle window resize
$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
}
var $el = $('<div></div>').appendTo(document.body)
.addClass('ui-widget-overlay').css({
width: this.width(),
height: this.height()
});
(dialog.options.stackfix && $.fn.stackfix && $el.stackfix());
this.instances.push($el);
return $el;
}
});
就可以修正這個問題, 裡面程式的邏輯比較複雜, 這邊就不多做說明了
總之是從國外copy paste回來的解法
可以在dialog modal:true的情況下, 在其中的CKEditor仍可以保有自身的功能正常
而我是直接把這段貼在ckeditor.js裡面
在這邊要致歉的是因為有一段時間了, 我也忘記這段程式碼從哪邊看來
就沒辦法把來源列在這邊讓人參考了
===================================================================================================================
最後一個部份是常用的ckeditor設定值
因為匯入了ckeditor\adapters\jquery.js 這個檔案
讓我們可以用一些jquery的方法去操作ckeditor
最簡單的方法就是可以在宣告的同時傳入設定值去調整ckeditor的屬性
例如說
$('[selector]').ckeditor(
{
width:400, height:500,
toolbarStartupExpanded : false
}
);
簡單說明如下,
a. width: ckeditor的寬度
b. height: ckeditor的高度
c. toolbarStartUpExpanded : toolbar預設顯示還是隱藏
還有其他東西就希望前輩幫我補充了
--
本文可能有理解錯誤 或不盡不實的地方
請路過的前輩不要客氣 用力打醒
這會是我們成長的主要養分