PDA

View Full Version : Xây dựng một Rich Text Editor - Phần 1



sacroyant
28-12-2007, 17:09
Đã có khá nhiều trình soạn thảo văn bản WYSIWYG miễn phí được share trên mạng, nhưng nếu bạn là một web developer đích thực, có thể một lúc nào đó bạn sẽ muốn xây dựng cho riêng mình một Rich Text Editor. Nếu vậy, bài viết này chắc hẳn sẽ đem lại cho bạn một chút gì đó hữu ích.

Thoạt tiên, khi nảy ra ý muốn viết 1 cái RTE, tôi đã nghĩ đến việc sử dụng 1 thẻ DIV để làm khung soạn thảo. Không khó trong việc giả lập con trỏ nhấp nháy, và chuyển các ký tự từ bàn phím vào trong phần tử DIV này. Một ví dụ là chương trình mô phỏng giao diện dòng lệnh của Window mà tôi đặt tên là Web Command Line (http://sacroyant.uni.cc/Examples/cmd/cmd.htm) (nó chỉ để chơi thôi chứ không giải quyết công việc gì :emlaugh:).

Nhưng rồi sau nhiều cuộc tìm kiếm, tôi đã phát hiện ra 1 điều quan trọng khác giúp cho công việc tự đơn giản hóa đi rất nhiều, đó là : DesignMode.

DesignMode là 1 thuộc tính của đối tượng document, giá trị mặc định của nó là "off". Khi bạn sửa đổi giá trị này thành "on", hồ sơ web trở thành dạng có thể chỉnh sửa - editable, và bạn có thể thao tác với trang web trong cửa sổ như đang làm việc trên MS Word ! Đây chính là bí quyết để xây dựng nên những RTE cho các trình duyệt web.

Bây giờ chúng ta sẽ làm 1 trình soạn thảo WYSIWYG đơn giản, gồm một trường nhập text, và các nút lệnh cho phép định dạng văn bản in đậm - B, in nghiêng - I, gạch dưới - U. Ngoài ra, chúng ta cũng thêm vào 2 nút cho phép chèn hình ảnh và liên kết. Sau cùng là một nút để gỡ bỏ các định dạng. Giao diện của editor trông sẽ như thế này :

http://farm3.static.flickr.com/2278/2142569192_1e4f841419_o.jpg

Khung soạn thảo là 1 iframe, như cách thường dùng của các RTE. Chúng ta cho nó 1 ID và dùng CSS để thiết lập kích thước và khả năng scroll :



<iframe id="textArea" style="width:500px;height:240px;overflow:auto;"></iframe>


Để biến vùng iframe này về dạng editable, chúng ta thiết lập giá trị của thuộc tính designMode thành on bằng script sau :




var editor = document.getElementById('textArea').contentWindow. document;
editor.designMode='On';
editor.open();
editor.write('<html><head></head><body></body></html>');
editor.close();


Đoạn code JavaScript này phải được gọi sau khi iframe đã hiện diện trong trang web.

contentWindow là 1 thuộc tính của các frames, iframes trong hồ sơ HTML.

document.getElementById('textArea').contentWindow cho phép tham chiếu đến đối tượng iframe mà định danh được thiết lập : ID = "textArea".

Trong Mozilla , chúng ta có thể tham chiếu đến 1 đối tượng cửa sổ iframe bằng script :


window.frames["myFrame"]

Script tương ứng cho IE là :

document.all.myFrame.contentWindow

Còn script mà chúng ta dùng sẽ thích hợp cho cả IE, Mozilla và Opera.

Như vậy, chúng ta có 1 biến toàn cục editor, để tham chiếu đến đối tượng document của phần tử iframe giả lập khung soạn thảo văn bản. Dòng lệnh tiếp theo thiết lập designMode của nó thành "on". Các lệnh open, write, close chèn vào iframe các tags cơ bản của 1 hồ sơ HTML, những gì nằm giữa <body> và </body> sẽ hiển thị trên khung soạn thảo như phần text mặc định của Editor.

Sau thiết lập designMode = "on", đối tượng document của iframe sẽ tự kích hoạt một số phương thức hỗ trợ thực hiện định dạng phần văn bản được chọn (selected text) bên trong nó. Chúng bao gồm :


queryCommandEnabled
queryCommandIndeterm
queryCommandState
queryCommandSupported
queryCommandValue


Trong đó, quan trọng hơn cả là 2 phương thức execCommand và queryCommandEnabled.

Syntax của execCommand như sau :



editableDocument.execCommand(sCommand [, bUserInterface] [, vValue])


Nếu không có text được chọn, phương thức này không làm gì cả.

Tham số bắt buộc sCommand là 1 chuỗi tên lệnh định dạng (command identifiers), chẳng hạn "bold", "italic"... QuirksMode (http://http://www.quirksmode.org/) liệt kê khá chi tiết những lệnh định dạng này, và cả cách chúng làm việc trong từng trình duyệt :

http://www.quirksmode.org/dom/execCommand.html

Tham số thứ hai, bUserInterface, thuộc dạng tùy chọn và mang 1 giá trị boolean (mặc định : false). Trong Mozilla, nếu đặt là true, bạn có thể nhận 1 lỗi (NS_ERROR_NOT_IMPLEMENTED).

Tham số thứ 3, vValue, cũng thuộc dạng tùy chọn. Bạn sẽ phải dùng đến nó trong một số trường hợp mà tham số đầu tiên cần 1 giá trị cụ thể. Chẳng hạn khi muốn định dạng màu chữ, tham số thứ nhất sẽ là "forecolor", và chúng ta cần tham số thứ 3 để cho trình duyệt biết màu gì sẽ được sử dụng. Ví dụ :


editableDocument.execCommand("forecolor", false, "#0000ff");

Hoặc khi chèn 1 hình ảnh, tham số thứ nhất sẽ là "insertimage", và tham số thứ 3 cho biết đường dẫn của hình ảnh đó :


editableDocument.execCommand('insertimage', false, imageURL);

Để biết 1 command có thể thực thi hay không, chúng ta dùng queryCommandEnabled. Phương thức này nhận 1 tham số là tên của command (như : "bold", "italic", "forecolor", "insertimage"...), và trả về 1 giá trị boolean cho biết khả năng thi hành command đó. Thông thường chúng ta kiểm tra command trước khi gọi nó. Script dưới đây kiểm tra command tạo liên kết, nếu có thể thực hiện thì sẽ chèn vào khung soạn thảo 1 HyperLink (aLink) :



if(editableDocument.queryCommandEnabled("createlink")){
editableDocument.execCommand('createlink', false, aLink);
}

Bây giờ, chúng ta xem xét các button. Chúng là những hình ảnh mà bạn tùy ý trình bày sao cho hợp lý. Thông thường các button định dạng nằm ngay trên khung soạn thảo như trong ví dụ mẫu này. Các lệnh in đậm, in nghiêng, gạch dưới được liên kết với hàm doFormat qua sự kiện click :



<img src="bold.gif" onclick="doFormat('bold');">
<img src="italic.gif" onclick="doFormat('italic');">
<img src="underline.gif" onclick="doFormat('underline');">


Hàm doFormat như sau :



function doFormat(a,b){
if(editor.queryCommandEnabled(a)){
if(!b){b=null;}
editor.execCommand(a,false,b);
}
}


Như vậy, doFormat nhận vào 2 tham số :

- a : tên của command
- b : giá trị của command

Ở đây, editor là biến toàn cục đã định nghĩa bên ngoài hàm như trình bày phía trên. Khi được gọi, doFormat sử dụng phương thức queryCommandEnabled của editor để kiểm tra khả năng thực thi command a. Sau đó, tiếp tục kiểm tra tham số thứ 2, nếu không thấy thì gán cho nó giá trị null. Nếu có thể thực thi command thì gọi phương thức execCommand.

Đối với việc chèn hình ảnh và liên kết, có một chút khác biệt, chúng ta viết 2 hàm addLink và insertImage dành riêng cho nhiệm vụ này. Chúng được gọi theo cách tương tự như 3 nút lệnh trước.



<img src="image.gif" onclick="insertImage();">
<img src="link.gif" onclick="addLink();">


Trong IE, bạn có thể viết :


editor.execCommand("CreateLink", true);

Hoặc :


editor.execCommand("InsertImage", true);

Trình duyệt này sẽ hiển thị một hộp thoại để người sử dụng nhập vào các tham số thích hợp :

http://farm3.static.flickr.com/2014/2143437544_9b83c775e1_o.jpg

http://farm3.static.flickr.com/2225/2143456580_e53ca630eb_o.jpg

Tuy nhiên tính năng này chưa được Mozilla và Opera hỗ trợ, vì vậy, một số người lập trình Rich Text Editor đã tự xây dựng các kiểu DialogBox riêng để thay thế. Việc đó không khó, nhưng trong bài viết này, chúng ta sẽ đơn giản hóa công việc bằng 1 hộp thoại prompt.


Dưới đây là hàm addLink :



function addLink(){
var aLink=prompt('Enter or paste a link :', '');
if(aLink){
doFormat('CreateLink', aLink);
}
}

Và hàm insertImage :



function insertImage(){
document.getElementById('textArea').contentWindow. focus();
var iURL=prompt('Enter or paste a URL :', '');
if(iURL){
doFormat('InsertImage', iURL);
}
}

Khi người sử dụng click trên nút [http://b.imagehost.org/0395/link1.gif], một hộp thoại prompt bật ra để họ nhập chuỗi siêu liên kết. Hàm addLink kiểm tra lại chuỗi này, nếu có giá trị thị gọi doFormat với
2 tham số : "CreateLink" - tên command, và aLink - URL đích do người dùng cung cấp.

Khi hàm insertImage được gọi, chúng ta sử dụng dòng lệnh đầu tiên để focus vào vùng soạn thảo. (Điều này là cần thiết cho trình duyệt IE, bạn thử bỏ đi và chạy thử chương trình thì sẽ hiểu tại sao !). Tiếp đó, 1 hộp thoại prompt mở ra yêu cầu người sử dụng nhập vào URL của hình ảnh. Cuối cùng, chúng ta gọi doFormat với command "InsertImage" và giá trị iURL mà người dùng đã nhập.

Nút lệnh [http://b.imagehost.org/0457/removeformatting.gif] cho phép gỡ bỏ mọi định dạng trên phần text được chọn.


<img src="removeformatting.gif" onclick="unformat();">

Chúng ta viết hàm xử lý như sau :


function unformat(){
doFormat('removeformat');
doFormat('unlink');
}

Không có gì để giải thích nhiều. Command "removeformat" loại bỏ toàn bộ các thiết lập kiểu dáng văn bản. Command "unlink" gỡ bỏ liên kết cho phần văn bản đó.

Cuối cùng, chúng ta có toàn bộ mã HTML và JavaScript như dưới đây :



<h1>Rich Text Editor</h1>
<table border="0" cellpadding="0" cellspacing="1" bgcolor="#e1f2ff">

<tr height="20">
<td>
&nbsp;
<img src="bold.gif" title="Bold" onclick="doFormat('bold');">
<img src="italic.gif" title="Italic" onclick="doFormat('italic');">
<img src="underline.gif" title="Underline" onclick="doFormat('underline');">
<img src="image.gif" title="Insert Image" onclick="insertImage();">
<img src="link.gif" title="Hyperlink" onclick="addLink();">
<img src="removeformatting.gif" title="Remove Formatting" onclick="unformat();">
</td>

</tr>
<tr>
<td align="center" bgcolor="#ffffff">
<iframe id="textArea" style="width:500px;height:240px;overflow:auto;"></iframe>
</td>
</tr>
</table>
<script type="text/javascript">
var editor = document.getElementById('textArea').contentWindow. document;
editor.designMode='On';
editor.open();
editor.write('<html><head></head><body></body></html>');
editor.close();

function doFormat(a,b){
if(editor.queryCommandEnabled(a)){
if(!b){b=null;}
editor.execCommand(a,false,b);
}
}
function addLink(){
var aLink=prompt('Enter or paste a link :', '');
if(aLink){
doFormat('CreateLink', aLink);
}
}
function insertImage(){
document.getElementById('textArea').contentWindow. focus();
var aLink=prompt('Enter or paste a URL :', '');
if(aLink){
doFormat('InsertImage', aLink);
}
}
function unformat(){
doFormat('removeformat');
doFormat('unlink');
}
</script>


Bây giờ thì Editor của chúng ta đã có thể hoạt động trên Mozilla, IE, Opera và Safari.

Demo :

http://sacroyant.uni.cc/Examples/Editor/V1/rte.htm

Phần sau, chúng ta sẽ tìm hiểu sâu hơn một số command khác để mở rộng tính năng cho editor này, đồng thời viết lại kịch bản điều khiển Editor theo kiểu hướng đối tượng. Hẹn gặp lại.

kiem_bo
28-12-2007, 19:07
nói gì thì nói đây là thứ tôi đang cần cảm ơn cái nha. Hy vọng bạn đưa thêm những bài có chất lượng như trên. Thích quá đi thôi. Đây giống như món quà năm mới bạn tặng cho anh em đó. TIếp nào

sacroyant
29-12-2007, 17:56
Định dạng văn bản tại chỗ :

bold : in đậm text
fontname : font chữ, vValue :tên font. VD : arial, verdana...
fontsize : khổ chữ, vValue : các số từ 1 đến 7.
forecolor : màu chữ. vValue : chuỗi tên hoặc mã màu. VD : #0000ff, navy...
hilitecolor : màu nền (1). vValue : chuỗi tên hoặc mã màu. VD : #0000ff, navy...
italic : làm nghiêng text
subscript : text thấp xuống so với bình thường
superscript : đẩy text lên cao hơn bình thường
underline : gạch dưới text

Định dạng khối văn bản :

heading : Định dạng cho một tiêu đề. vValue : <h1>, <h2>, <h3>, <h4>, <h5>, <h6>.
indent : cho khối văn bản lui vào 1 tab
insertorderedlist : liệt kê theo số thứ tự
insertunorderedlist : liệt kê không đánh số.
justifycenter : căn giữa
justifyfull : dàn đều 2 biên
justifyleft : căn trái
justifyright : căn phải
outdent : cho khối văn bản lui ra 1 tab

Các command khác :

createlink : tạo liên kết. vValue : chuỗi URL
delete : xóa phần selection
inserthorizontalrule : chèn vào 1 phần tử <hr>
inserthtml : chèn vào 1 chuỗi HTML (2)
insertimage : chèn hình ảnh. vValue : đường dẫn đến file ảnh.
removeformat : loại bỏ các định dạng ở phần selection.
unlink : loại bỏ liên kết ở phần selection.

Các command điều khiển editor :

undo : khôi phục lại tình trạng trước khi có 1 thay đổi được ghi nhận (3)
redo : khôi phục lại tình trạng trước khi undo 1 bước.
selectall : chọn toàn bộ nội dung editor.

Danh sách trên chưa đầy đủ, nhưng là những gì cơ bản nhất cho 1 trình soạn thảo văn bản. Chúng là các commands nhận được sự hỗ trợ chung của nhiều trình duyệt.

Nhắc lại cú pháp của execCommand :

editableDocument.execCommand(sCommand [, bUserInterface] [, vValue])

Trong đó :

editableDocument : tên biến tham chiếu đến phần tử document của đối tượng iframe được dùng để giả lập khung soạn thảo.
sCommand : chuỗi tên command. Không phân biệt hoa - thường.
bUserInterface : biến tùy chọn hiển thị các DialogBox. Luôn thiết lập là false để tránh lỗi trong Mozilla và Opera.
vValue : giá trị cho command. Nếu command không cần chỉ định giá trị, sử dụng null.

Thông thường vValue là 1 chuỗi, ngoại trừ giá trị cho kích thước chữ có thể để dạng interger, nhưng nói chung vẫn nên đưa về kiểu string.

* Chú thích :


Với IE, cần thay bằng command backcolor.
Chỉ duy nhất Mozilla hỗ trợ command này. Với IE, có thể dùng các command cụ thể cho từng đối tượng muốn chèn, như : InsertInputButton, InsertTextArea, InsertMarquee... Xem thêm tại đây (http://msdn2.microsoft.com/en-us/library/ms533049%28VS.85%29.aspx).
Các thay đổi được ghi nhận có thể là bất cứ hành động nào làm khác đi nội dung vốn có trong Editor, chẳng hạn như việc gõ vào, xóa đi, hay đổi màu 1 ký tự... Undo và Redo chỉ làm việc hoàn hảo trong Mozilla.

temp2
29-12-2007, 17:58
đề nghị những ai có ý kiến, góp ý, đả kích, khen chê... xung quanh mục tiêu của cái topic này (và cũng của sacroyant) nên hạn chế lại bớt nhằm tránh làm loãng cái topic này ra

chỉ nên post khi thực sự cảm thấy rất cần thiết và nên post các bài mang tính xây dựng cho cái editor, chớ đừng post linh tinh, đây là một topic rất có ý nghĩa, ko cần các spammer/comment/suggestion vô thưởng vô phạt


các chủ nhân của những bài viết vô thưởng vô phạt nên tự delete by yourself đi, coi như là 1 hình thức tự kiểm điểm dzậy. Cho đến khi nào bạn sacroyant tuyên bố kết thúc cái tut này thì mọi người cứ "tự nhiên như người Hà Nội"; còn bây giờ nên để cho nó xúc tích và cô đọng và liền mạch hơn

amida
29-12-2007, 18:28
Good job man :)
1 point cho bài viết

soccerervn
29-12-2007, 18:59
Tuyệt vời quá, cảm ơn sacroyant!

greenbeetle
29-12-2007, 20:56
Bài viết rất hay ! :) Thank

kiem_bo
30-12-2007, 07:49
một câu hỏi nhỏ nha. Làm cách nào để lấy nội dung những thứ mình đang gõ. Tôi muốn thay <ifframe> bằng <textare> thì mình thay đổi như thế nào

sacroyant
30-12-2007, 10:10
Cảm ơn mọi người đã hưởng ứng topic này :cheers:


một câu hỏi nhỏ nha. Làm cách nào để lấy nội dung những thứ mình đang gõ. Tôi muốn thay <iframe> bằng <textarea> thì mình thay đổi như thế nào

Bài viết này mình nói về cách viết 1 trình soạn thảo WYSIWYG dựa trên chế độ DesignMode của đối tượng hồ sơ HTML. Chỉ với 1 iframe, chúng ta mới có thể chèn vào trang web hiện tại 1 hồ sơ HTML, rồi sử dụng nó ở chế độ DesignMode ! Còn cách lấy nội dung từ trình soạn thảo thì sẽ được đề cập đến sau :w00t:

cuonphong
30-12-2007, 12:11
Thank you very much, mình cũng đang cần cái này

beham
30-12-2007, 19:43
Tôi xin thêm cái switch giữa chế độ code và chế độ deisgn mặc định + lấy nội dung mã HTML trong richtext mà mình sẽ cần khi "post" bài

<html>

<head>
<meta http-equiv="Pragma" content="No-cache">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="Descripton" content="Simple Rich Text Editor ">
<meta name="Author" content="Sacroyant Nguyen">
<meta name="ContactEmail" content="sacroyant@vninformatics.com">
<title>Rich Text Editor - Sacroyant Nguyen</title>
<link rel="stylesheet" type="text/css" href="rte_files/style.css">
</head>

<body>

<table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
<tr>
<td align="center">
<h1>Rich Text Editor</h1>
<table bgcolor="#e1f2ff" border="0" cellpadding="0" cellspacing="1">
<tr height="20" id="menuArea">
<td>&nbsp;
<img src="rte_files/bold.gif" title="Bold" onclick="doFormat('bold');">
<img src="rte_files/italic.gif" title="Italic" onclick="doFormat('italic');">
<img src="rte_files/underline.gif" title="Underline" onclick="doFormat('underline');">
<img src="rte_files/image.gif" title="Insert Image" onclick="insertImage();">
<img src="rte_files/link.gif" title="Hyperlink" onclick="addLink();">
<img src="rte_files/removeformatting.gif" title="Remove Formatting" onclick="unformat();">
</td>
</tr>
<tr>
<td align="center" bgcolor="#ffffff">
<iframe id="textArea" style="overflow: auto; width: 500px; height: 240px;">
</iframe>
<textarea id="codeArea" style="overflow: auto; width: 500px; height: 240px; display: none"></textarea>
</td>
</tr>
<tr>
<td>
<input id="btnSwitch" type="button" value="Switch To Code Mode" onclick="switchMode ();"></td>
</tr>
<tr>
<td>
<input type="button" value="Get Content" onclick="getContent ();"></td>
</tr>
</table>
<script type="text/javascript">
var editor = document.getElementById('textArea').contentWindow. document;
editor.designMode='On';
editor.open();
editor.write('<html><head></head><body></body></html>');
editor.close();

function doFormat(a,b){
if(editor.queryCommandEnabled(a)){
if(!b){b=null;}
editor.execCommand(a,false,b);
}
}
function addLink(){
var aLink=prompt('Enter or paste a link :', '');
if(aLink){
doFormat('CreateLink', aLink);
}
}
function insertImage(){
document.getElementById('textArea').contentWindow. focus();
var aLink=prompt('Enter or paste a URL :', '');
if(aLink){
doFormat('InsertImage', aLink);
}
}

function unformat(){
doFormat('removeformat');
doFormat('unlink');
}

var mode = "DESIGN";
function switchMode ()
{
if (mode == "DESIGN")
{
document.getElementById('textArea').style.display = "none";
document.getElementById('menuArea').style.display = "none";
document.getElementById('codeArea').style.display = "";
document.getElementById('codeArea').value = editor.body.innerHTML;
document.getElementById('codeArea').focus ();
document.getElementById('btnSwitch').value = "Switch To Design Mode";
mode = "CODE";
}
else
{
document.getElementById('menuArea').style.display = "";
document.getElementById('textArea').style.display = "";
document.getElementById('codeArea').style.display = "none";
editor.body.innerHTML = document.getElementById('codeArea').value;
document.getElementById('textArea').focus ();
document.getElementById('btnSwitch').value = "Switch To Code Mode";
mode = "DESIGN";
}
}

function getContent () {
if (editor) alert (editor.body.innerHTML);
}
</script>
<hr width="70%">Author by
<a href="http://sacroyant.googlepages.com/index.htm?nl=vi">Sacroyant Nguyen</a>
- Email : <a href="mailto:sacroyant@vninformatics.com">sacroyant@vninformatics.com</a>
- ©2007 </td>
</tr>
</table>

</body>

</html>

sacroyant
30-12-2007, 23:23
@ beham : Rất vui với sự tham gia của bạn. Phần tiếp theo mình sẽ viết lại mã điều khiển để tối ưu hóa code.

@ kiem_bo : Bổ sung thêm phần trả lời dành cho câu hỏi của bạn hôm qua :


một câu hỏi nhỏ nha... Tôi muốn thay <iframe> bằng <textarea> thì mình thay đổi như thế nào.


FireFox 3 đã hỗ trợ thuộc tính contentEditable. Như vậy có nghĩa là với IE 5+ và FireFox 3, chúng ta có thể gõ text trên bất cứ phần tử nào, sau khi thiết lập giá trị true cho thuộc tính contentEditable của nó. Ví dụ :


<div
contenteditable="true"
style="width:500px;height:200px;border:1px inset black; overflow:auto;">

Có thể xử lý văn bản ở đây như trong textArea

</div>

Và việc làm 1 WYSIWYG Editor sẽ trở nên dễ dàng hơn nữa :



<script language="javascript">
function doFormat(cmd) {
document.execCommand(cmd, null, null);
}
</script>
<button onclick="doFormat('bold');"><b>B</b></button><BR>
<div
contenteditable="true"
style="width:500px;height:200px;border:1px inset black; overflow:auto;">

</div>

Xem ví dụ cụ thể tại đây. (http://starkravingfinkle.org/blog/wp-content/uploads/2007/07/contenteditable.htm)

cuonphong
31-12-2007, 11:07
Hi all,
Như vậy vấn đề mình sử dụng đoạn script này thế nào trong web, phải copy code cho mỗi project à ?
Sẽ hay hơn nếu build thành 1 DLL hay 1 user control
chỉ việc drag and drop thì sướng quá :)

superthin
31-12-2007, 11:16
Lâu lắm rồi mới đọc được một topic chất lượng như thế này. Cám ơn sacroyant (http://ddth.com/member.php?u=62777) nhé, mình đang cần một cái như vậy, thử xem thế nào.

jiSh@n
31-12-2007, 13:00
Hi all,
Như vậy vấn đề mình sử dụng đoạn script này thế nào trong web, phải copy code cho mỗi project à ?
Sẽ hay hơn nếu build thành 1 DLL hay 1 user control
chỉ việc drag and drop thì sướng quá :)

Thật ko thể tin được :bored: Tín đồ M$ có khác:emlaugh: Đi tong cái topic hay của người ta rồi.

sacroyant
31-12-2007, 22:11
Khi nắm được những khái niệm xung quanh thuộc tính designMode và phương thức execCommand, việc xây dựng Rich Text Format Editor không còn là điều khó khăn nữa. Có lẽ những bạn nào mà qua topic này, lần đầu tiên nghe nói đến các khái niệm trên, sẽ có cùng cảm giác như vậy. Hiểu được vấn đề là giải quyết được vấn đề.

Các trình WYSIWYG xây dựng sẵn thường khá cồng kềnh. Chúng càng cố khoác lên mình dáng vẻ của các ứng dụng soạn thảo văn bản desktop thì hình thức càng rườm rà, bề bộn, với những tính năng mà có thể chúng ta không bao giờ dùng đến.

Đây là một số trình soạn thảo WYSIWYG phổ biến :


* Free Rich Text Editor (http://www.freerichtexteditor.com/page/3.htm)
* SPAW Editor (http://www.solmetra.com/en/disp.php/en_products/en_spaw/en_spaw_demo)
* Xinha (http://xinha.webfactional.com/)
* Through-The-Web Editor (http://koivi.com/WYSIWYG-Editor/)
* Cross-Browser Rich Text Editor (http://kevinroth.com/rte/demo.htm)

Các Editor cũng giống như mọi ứng dụng nền web, đều có hạn chế là phải phụ thuộc vào mức độ hỗ trợ của các trình duyệt. Một ứng dụng web có thể hoạt động trong nhiều trình duyệt khác nhau, không có lỗi khi chạy, và ít rắc rối, thì dễ gây cảm tình hơn những trò hoa lá.

Về phía những editor mà các dịch vụ web sử dụng thì cái của Gmail (http://mail.google.com/) hợp với mỹ cảm của tôi hơn cả. Ở đó có sự hài hòa giữa tính đơn giản, vẻ đẹp trang nhã và khả năng hoạt động chuẩn xác, hoàn hảo.

Do bài viết này chỉ nhằm mục đích giới thiệu cách xây dựng trình soạn thảo WYSIWYG, nên chúng ta vẫn giữ nguyên hình thức của bản trước mà không cần thêm các nút lệnh định dạng khác trên toolBar, tránh làm phức tạp vấn đề.

Chúng ta mở đầu bằng đoạn script :




var RTE=null;
var isIE=document.all?true:false;
var isMz=(navigator.appName=='Netscape')?true:false;

function rel(id){
return document.getElementById (id)||null;
}
function setHTML(el,sHTML){
if(rel(el)){
rel(el).innerHTML=sHTML;
}
else{
alert('The element "'+el+'" not found !');
}
}
function setBtnAction(btnID, Action){
var el = rel(btnID);
if(el.addEventListener){
el.addEventListener('click', new Function(Action), false);
}
else if (el.attachEvent){
el.attachEvent('onclick', new Function(Action));
}
}


rel trả về phần tử dựa trên id của nó. setHTML có nhiệm vụ gán code HTML vào 1 phần tử nào đó.

setBtnAction chỉ định 1 hành động cho 1 button dưới sự kiện click. Hàm này nhận vào 2 tham số : ID của button và chuỗi tên hành động. Ví dụ chúng ta có button btnBold hiện diện dưới dạng 1 icon nhỏ :


<img id="btnBold" src="bold.gif" title="Bold">

Nếu muốn chương trình thực thi lệnh doFomat("bold"), khi click vào hình ảnh này, chúng ta chỉ việc gọi hàm :


setBtnAction('btnBold', 'doFormat("bold")');

Khi chuỗi 'doFormat("bold")' được truyền vào hàm setBtnAction, vì addEventListener và attachEvent bắt buộc tham số thứ 2 phải là 1 hàm, nên setBtnAction sẽ dùng chuỗi này để tạo ra 1 đối tượng Function với toán tử new.

Giữ nguyên các thành phần điều khiển Editor như cũ, chúng ta viết lại code HTML :



<table border="0" cellpadding="0" cellspacing="1" bgcolor="#e1f2ff">
<tr height="20">
<td>
&nbsp;
<img id="btnBold" src="bold.gif">
<img id="btnItalic" src="italic.gif">
<img id="btnUnderline" src="underline.gif">
<img id="btnInsertImage" src="image.gif">
<img id="btnAddLink" src="link.gif">
<img id="btnUnformat" src="removeformatting.gif">
</td>
</tr>
<tr>
<td align="center" bgcolor="#ffffff">
<span id="wysiwyg"></span>
</td>
</tr>
</table>


Thay vì nhúng các hàm vào từng button, chúng ta đã cho mỗi hình ảnh một giá trị ID.

Nếu hình dung điều khiển WYSIWYG của chúng ta như 1 đối tượng, nó có thể mang các thuộc tính căn bản như : tên, kích thước vùng làm việc, nội dung bên trong. Và bên cạnh đó là 1 loạt các phương thức thi hành việc định dạng văn bản : chèn link, chèn hình ảnh... Đây là hàm dựng :



function RichTextEditor(sID, oContain, sDefaultText, iWidth, iHeight){

this.ID=sID;
this.content=sDefaultText;
this.width=(iWidth>300?iWidth:500);
this.height=(iHeight>80?iHeight:200);

var sEditor='<iframe id="'+this.ID;
sEditor+='" style="width:'+this.width;
sEditor+='px;height:'+this.height;
sEditor+='px;overflow:auto;"></iframe>';

setHTML(oContain,sEditor);

this.UI=document.getElementById(this.ID).contentWi ndow;
this.editor=this.UI.document;

with(this.editor){
designMode='On';
open();
write('<html><head></head><body>'+this.content+'</body></html>');
close();
}
}


Các tham số :

sID : chuỗi tên riêng cho mỗi Editor, bằng cách này, chúng ta có thể sử dụng nhiều Editor trên cùng 1 trang web.
oContain : phần tử chứa Editor mà khung soạn thảo sẽ được tạo ra bên trong.
sDefaultText : văn bản mặc định hiển thị khi Editor mở ra. Đây là 1 chuỗi HTML.
iWidth : chiều rộng của khung soạn thảo.
iHeight : chiều cao của khung soạn thảo.

Trong hàm dựng, chúng ta thiết kế các thuộc tính :

ID : định danh riêng
content : nội dung văn bản trong editor
width : chiều rộng
height : chiều cao
UI : tham chiếu đến khung iframe
editor : tham chiếu đến đối tượng document của khung iframe. Biến này trực tiếp thi hành các command.

Hàm doFormat ở bản cũ sẽ trở thành phương thức formatText của lớp đối tượng RichTextEditor :



RichTextEditor.prototype.formatText=function(comma nd, value){
if(this.editor.queryCommandEnabled(command)){
if(!value){value=null;}
this.editor.execCommand(command,false,value);
}
}



Và tương tự cho addLink, insertImage, unformat :



RichTextEditor.prototype.addLink=function(){
var aLink=prompt('Enter or paste a link :', '');
if(aLink){
this.formatText('CreateLink', aLink);
}
}
RichTextEditor.prototype.insertImage=function(){
this.UI.focus();
var aLink=prompt('Enter or paste a URL :', '');
if(aLink){
this.formatText('InsertImage', aLink);
}
}
RichTextEditor.prototype.unformat=function(){
this.formatText('removeformat');
this.formatText('unlink');
}


Ngoài ra chúng ta cũng thêm vào 1 phương thức mới là getContent để lấy nội dung văn bản :


RichTextEditor.prototype.getContent=function(){
return this.editor.body.innerHTML;
}

Cuối cùng là 1 hàm dùng để khởi tạo trình soạn thảo, được gọi sau khi trang load xuống hoàn chỉnh :



function init(){

RTE=new RichTextEditor('RTE', 'wysiwyg', '', 500, 240);

setBtnAction('btnBold', 'RTE.formatText("bold")');
setBtnAction('btnItalic', 'RTE.formatText("italic")');
setBtnAction('btnUnderline', ' RTE.formatText("underline");');
setBtnAction('btnInsertImage', 'RTE.insertImage();');
setBtnAction('btnAddLink', 'RTE.addLink();');
setBtnAction('btnUnformat', ' RTE.unformat();');
}


Biến RTE được dùng làm một thể hiện của lớp RichTextEditor. Các dòng sau thiết lập hành động cho từng nút lệnh trên toolBar.

init được gọi cùng sự kiện onload :


window.onload=init ;

Và thế là chúng ta đã có phiên bản Rich Text Editor mới, tuy không thay đổi trên giao diện, nhưng cấu trúc chương trình đã trở nên chặt chẽ hơn hẳn :

Demo :
http://sacroyant.uni.cc/Examples/Editor/V1/rte2.htm


Còn đây là sản phẩm hoàn thiện :


http://d.imagehost.org/0758/Editor.png (http://sacroyant.uni.cc/Examples/Editor/)

Từ bản demo rút gọn đến sản phẩm sau cùng chỉ còn một quãng đường ngắn, và chắc hẳn bạn sẽ cảm thấy dễ chịu hơn nếu đi tới đó một mình lol

kiem_bo
31-12-2007, 22:42
nếu được bạn có thể đưa cho anh em bài viết tạo bộ gõ tiếng việt cho web ko. Cái này tôi cần vì tôi thích xài hàng tự cung tự cấp chứ ko thích xài hàng có sẳn. Vậy là wysiwyg tôi làm được rồi còn bộ gõ tiếng việt nữa. Chỉ cho anh em luôn đi. Chỉ còn 1h20 phút nữa là năm mới rồi

sacroyant
01-01-2008, 00:08
nếu được bạn có thể đưa cho anh em bài viết tạo bộ gõ tiếng việt cho web ko. Cái này tôi cần vì tôi thích xài hàng tự cung tự cấp chứ ko thích xài hàng có sẳn. Vậy là wysiwyg tôi làm được rồi còn bộ gõ tiếng việt nữa. Chỉ cho anh em luôn đi. Chỉ còn 1h20 phút nữa là năm mới rồi

Sài hàng tự làm vẫn là thích nhất, điểm này thì em nhất trí hoàn toàn với bác. Còn về bộ gõ trên Editor đó thì em dùng HIM đấy chứ, thấy cũng chưa ổn định. Cơ chế của bộ gõ trên web gần giống kiểu dùng hook trong lập trình truyền thống. Có điều em chưa tìm hiểu kỹ về các bảng mã. Để năm sau vậy bác nhé :w00t:

@ lkn2 : bác nói về phiên bản nào thế. Cái editor của em cứ vài hôm lại có thay đổi :)

superthin
01-01-2008, 00:50
À, bây giờ thì mình hiểu rằng các bác ở đây đang reinvent the wheel nhiều thứ. Để làm gì thế nhỉ?

sacroyant
01-01-2008, 02:08
À, bây giờ thì mình hiểu rằng các bác ở đây đang reinvent the wheel nhiều thứ. Để làm gì thế nhỉ?

Em dùng từ "xây dựng" chứ không phải "phát minh" đâu bác :yes:

Một người lập trình, nếu có điều kiện tự tay làm một số thứ, chắc chắn sẽ tốt cho quá trình phát triển kỹ năng của anh ta hơn là chỉ bê những cái được làm sẵn về dùng.

Dễ nhận thấy là việc tự làm 1 sản phẩm đã bao hàm cả việc mang những thứ có sẵn về nghiên cứu để tìm hiểu bản chất của vấn đề cần giải quyết :)

3do
01-01-2008, 07:21
À, bây giờ thì mình hiểu rằng các bác ở đây đang reinvent the wheel nhiều thứ. Để làm gì thế nhỉ?

để cho người chưa biết tham khảo, biết cơ chế hoạt động của nó như thế nào. Biết đâu nó đem lại 1 ý tưởng mới cho ai đó lol

jiSh@n
01-01-2008, 13:10
À, bây giờ thì mình hiểu rằng các bác ở đây đang reinvent the wheel nhiều thứ. Để làm gì thế nhỉ?

Ai cũng nghĩ như bác thì hiện nay đã ko có những cái như TinyMCE hay FCkEditor... Cái gì cũng có lý do của nó.

superthin
01-01-2008, 16:49
Rồi thì các bác ngồi viết luôn một ngôn ngữ lập trình, trình duyệt khác luôn, khỏi có phải dùng HTML, JavaScript, IE, FireFox luôn nhé. Tại sao không phân tích một cái người ta làm sẵn và đặt câu hỏi: "Liệu ta có làm tốt hơn không? Cách làm như thế nào?" Và mổ xẻ để đưa ra một cái gì đó hay hơn. Đàng này đi lắp một chiếc xe bò để mang lên siêu xa lộ chạy, và sau đó thì người ta download phần cứng về, các bác thì dắt bê con về làm món bê thui :)

sacroyant
01-01-2008, 17:35
@ lkn2 : đêm nay rảnh em code lại hết.

Có lẽ chúng ta không cần phát minh ra bóng đèn, nhưng phải biết cách làm ra được bóng đèn. Một lần nữa đề nghị bác superthin phân biệt cho kỹ giữa " phát minh" và "chế tạo" lol

Chính bác đã nói :


...Tại sao không phân tích một cái người ta làm sẵn và đặt câu hỏi: "Liệu ta có làm tốt hơn không? Cách làm như thế nào?" Và mổ xẻ để đưa ra một cái gì đó hay hơn.

Tuto này cũng nhằm mục đích mổ xẻ bản chất của các editor trên nền web như TinyMCE hay FCkEditor. Khi hiểu được những thứ này thì mới làm được như chúng. Làm được như chúng rồi mới nghĩ đến chuyện làm tốt hơn chúng :rolleyes:

Topic này chỉ phân tích cách lập trình editor, chứ không có nhiệm vụ share một editor hoàn chỉnh :emlaugh:

conan1212
01-01-2008, 17:51
Mặc dù cái này mình làm đc khi cố làm cái wysiwyg có công thức toán. Nhưng mà để viết ra chi tiết như thế này cho mọi người đọc như Sacroyant thì chịu. Ông này chịu khó đây, mà nhà chắc cũng giàu lắm :D. Cám ơn vì đóng góp của bạn cho forum nhé :).

zoejoe
01-01-2008, 18:02
hay quá chừng !! Đây đúng là thứ mình đang cần. Mấy hôm nay nghĩ về cái này mà không có tài liệu nào liên qua hêt !
Mình đang làm Project www.zhome.info Có gì giúp đỡ mình với !
níck y! zoejoe.listen;
mail zoejoe.listen@gmail.com
Thanks

jiSh@n
01-01-2008, 21:39
Rồi thì các bác ngồi viết luôn một ngôn ngữ lập trình, trình duyệt khác luôn, khỏi có phải dùng HTML, JavaScript, IE, FireFox luôn nhé. Tại sao không phân tích một cái người ta làm sẵn và đặt câu hỏi: "Liệu ta có làm tốt hơn không? Cách làm như thế nào?" Và mổ xẻ để đưa ra một cái gì đó hay hơn. Đàng này đi lắp một chiếc xe bò để mang lên siêu xa lộ chạy, và sau đó thì người ta download phần cứng về, các bác thì dắt bê con về làm món bê thui :)

Muốn làm tốt hơn trước hết phải làm được bằng họ. Muốn bằng họ thì phải trả lời được câu hỏi : Họ đã làm điều đó như thế nào?

quangtrong
01-01-2008, 22:20
Cám ơn vì tất cả, mình trưởng thành lên rất nhiều...

The Old Man
01-01-2008, 22:40
Cám ơn bác Sacroyant.

Không phải bác reinvent the wheel như những người không biết code khác đã nói, mà là bác làm ra bánh xe đem tặng cho mọi người nhất là những người bước đi không vững.

Đừng nghe lời bàn ra của những người chỉ biết nhắm mắt "mượn" ,"xin", hay "chôm" để không phải "Reinvent".

Một tràng pháo tay cho bác Sacroyant.

sacroyant
01-01-2008, 23:58
Đúng vậy ! Phải làm được bằng chính đôi tay và khối óc của mình thì mới có khả năng vuơn lên được ............

Anh sacroyant giỏi quá ! Anh đang học đại học hay học THPT vậy ? Cái lập trình Web này anh tự tìm tòi học hỏi hay học ở đâu đó mà giỏi quá vậy ! Em phục anh luôn. Ngay cả vBulletin cũng không dùng cái Richtext vừa đẹp, vừa đơn giản cho người không thạo mà dùng cái khác, nếu không biết sơ về HTML thì ....... !

Nghe bác nói mà ngại quá. Em là dân amateur, mày mò tự học thôi chứ có qua trường lớp gì đâu :huh:

Thật phấn khởi khi đọc các ý kiến tán thưởng :w00t: Phần tiếp theo sẽ bàn cách giải quyết các command "copy" và "paste", kết hợp editor với AJAX để tạo ra chế độ auto save... :goodluck:

TheHeTre
02-01-2008, 08:34
Hi, bài viết chất lượng lắm @sacroyant. Cố gắng phát triển tiếp nhé. Nhân tiên stick lên để mọi người tiện theo dõi.

temp2
02-01-2008, 10:40
đề nghị những ai có ý kiến, góp ý, đả kích, khen chê... xung quanh mục tiêu của cái topic này (và cũng của sacroyant) nên hạn chế lại bớt nhằm tránh làm loãng cái topic này ra

chỉ nên post khi thực sự cảm thấy rất cần thiết và nên post các bài mang tính xây dựng cho cái editor, chớ đừng post linh tinh, đây là một topic rất có ý nghĩa, ko cần các spammer/comment/suggestion vô thưởng vô phạt


các chủ nhân của những bài viết vô thưởng vô phạt nên tự delete by yourself đi, coi như là 1 hình thức tự kiểm điểm dzậy. Cho đến khi nào bạn sacroyant tuyên bố kết thúc cái tut này thì mọi người cứ "tự nhiên như người Hà Nội"; còn bây giờ nên để cho nó xúc tích và cô đọng và liền mạch hơn

sacroyant
03-01-2008, 13:00
Clipboard là một vùng nhớ tạm trong window, nơi chứa dữ liệu mà chúng ta đã copy hay cut. Các ứng dụng khác nhau vẫn được phép sử dụng chung khối dữ liệu này. Có nghĩa là có thể bạn copy text trong MS Word, sau đó dán lên khung soạn thảo của Google Docs (http://docs.google.com/).

Các command "copy", "cut", "paste" cho phép RTE của chúng ta làm điều này. Nhưng vì lý do an toàn, ngoại trừ IE, các trình duyệt khác đều mặc định vô hiệu hóa tính năng trên.

Nếu Java Script cố gọi thử lệnh này trên Mozilla, trình duyệt sẽ trả về lỗi :


Error: [Exception... "Access to XPConnect service denied" code: "1011" nsresult: "0x805303f3 (NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED)"

Google Docs bắt lỗi này lại và cho ra thông báo :


http://farm3.static.flickr.com/2111/2158772881_27c098df3f_o.jpg

Nhiều phương pháp đã được đưa ra để khắc phục trở ngại này, đồng thời tránh khỏi việc phải yêu cầu người dùng thay đổi cấu hình trên hệ thống của họ. Một trong những phương pháp khá thú vị là sử dụng Action Script. Do ngôn ngữ này có thể can thiệp sâu vào hệ thống của client nên 1 chương trình flash đã được viết ra để bổ sung khả năng vào nơi mà Java Script bất lực. (Xem chi tiết (http://www.jeffothy.com/weblog/clipboard-copy/))

Nhưng nếu bạn từng sử dụng Zoho Writer (http://writer.zoho.com), bạn sẽ thấy họ vẫn làm cho các lệnh copy, cut và paste hoạt động được trên FireFox. Lần tìm giải pháp trong source code của một ứng dụng web phức tạp như Zoho Writer (http://writer.zoho.com) là một việc không mấy dễ dàng. Chỉ còn cách dựa trên các biểu hiện để phán đoán.

Điều dễ nhận thấy là chúng ta không thể đem paste khối văn bản được copy hay cut từ khung soạn thảo của Zoho Writer vào MS Word, và ngược lại, cũng không thể dùng lệnh paste trên khung soạn thảo của Zoho Writer để chèn vào nó những gì có trong clipboard của windows. Từ đó cho thấy nội dung chỉ được lưu trong 1 biến tạm của kịch bản javascript mà Zoho Writer sử dụng.

Tuy nhiên, cách làm của Zoho Writer (http://writer.zoho.com) chưa hoàn toàn thuyết phục. Điểm hạn chế của nó là không ngăn cản được sự "merge style". Xem hình minh họa bên dưới :


http://farm3.static.flickr.com/2351/2158265821_560faa7706.jpg (http://farm3.static.flickr.com/2351/2158265821_291e7efe0b_o.jpg)

Đầu tiên tôi chọn đoạn text "thuộc tính designMode", nhấn lệnh Copy bên trên toolBar, rồi đặt con trỏ vào cuối dòng tiêu đề - "Viết class cho editor", sau đó nhấn Paste. Kết quả là chuỗi được paste sẽ mang định dạng của chuỗi tiêu đề bài viết mà không giữ nguyên kiểu dáng của nó. Nếu bạn quen dùng MS Word thì điều này thật đáng bực mình.

Chúng ta sẽ giải quyết vấn đề một cách triệt để hơn Zoho. Ý tưởng cơ bản là tạo ra 1 bản sao chính xác của phần text được chọn, lưu nó vào một biến tạm. Biến này đóng vai trò clipboard, được xem như 1 thuộc tính của lớp RichTextEditor.

Với mỗi command, chúng ta sẽ có cách xử lý tương ứng :


copy : tạo bản sao của selection, lưu vào biến tạm.
cut : copy rồi xóa đi phần text selection.
paste : gắn chuỗi trong biến tạm vào lại editor.


Để thực hiện ý tưởng, trước hết hãy tìm hiểu đôi chút về Selection và Range.

Range là một phần nội dung trong hồ sơ HTML, thường liên quan đến phần text được highlight bởi người sử dụng. Đối tượng này mô tả tất cả nội dung giữa điểm đầu và điểm cuối. Với các phương thức và thuộc tính của đối tượng này, chúng ta có thể làm khá nhiều việc với phần văn bản đang ở trạng thái selected. Cùng một thời điểm, có thể tồn tại nhiều đối tượng Range.

Selection là đối tượng chỉ phần text đang trong trạng thái selected và đang được active. Nó cung cấp thông tin về văn bản và toàn bộ các phần tử nằm trong phần text đang được chọn. Không hoàn toàn giống với Range, Selection liên quan đến các đối tượng văn bản, như : từ, câu, đoạn... Trong 1 thời điểm chỉ có thể tồn tại 1 Selection.

Điểm khác biệt giữa Range và Selection khá tinh tế. Lấy 1 minh họa như hình dưới đây cho dễ hiểu :


http://farm3.static.flickr.com/2337/2161283730_eb0c77167f_o.jpg

Nếu bạn tạo 1 Selection từ phần được chọn, đối tượng này sẽ phản ánh chuỗi "ject</i> to modify the document <b>select". Trong khi Range phân tích cấu trúc DOM của hồ sơ và cho biết cụ thể đoạn "ject" nằm trong phần tử <i>, đoạn "select" nằm trong phần tử <b>, và toàn bộ selection cùng thuộc phần tử <BODY>.

Chính vì vậy, việc sử dụng Range cho phép chúng ta không những lấy ra phần text selection mà cả các phần tử chứa nó - các tag HTML, nghĩa là text selection có kèm theo định dạng :rolleyes:

VỚi Opera và Mozilla, bạn có thể tạo Range bằng phương thức createRange của đối tượng document, hoặc phương thức getRangeAt của đối tượng Selection. Khi chọn 1 đoạn text bất kỳ trên trang web, bạn có thể lấy nội dung phần được chọn bằng phương thức getSelection của window. Phương thức này cũng đồng thời tạo ra một đối tượng Selection.

Range có khá nhiều thuộc tính và phương thức. Danh sách đầy đủ bạn có thể xem tại đây (http://developer.mozilla.org/en/docs/DOM:range). Trong số này chúng ta sẽ cần đến 2 phương thức extractContents và cloneContents.

cloneContents trả về 1 bản sao chính xác của range hiện thời, tức là phần text được chọn. extractContents cũng tương tự cloneContents, nhưng loại bỏ range gốc. Kết quả trả về từ 2 phương thức này có dạng 1 đối tượng documentFragment. Tới đây chúng ta rơi vào lãnh địa của XML và DOM.

Vì documentFragment giống như mọi phần tử trong 1 hồ sơ XML, chúng ta sẽ dùng phương thức serializeToString của đối tượng XMLSerializer được các trình duyệt tuân thủ chuẩn W3C hỗ trợ, để chuyển phần hồ sơ XML đó về dạng chuỗi thông thường.


Ngược lại với serializeToString của đối tượng XMLSerializer là phương thức parseFromString của đối tượng DOMParser, cho phép bạn thao tác trên 1 chuỗi text bình thường như với một tập hợp node trong hồ sơ XML.

Chẳng hạn bạn có chuỗi s='<result>125789</result>', đây không phải là dữ liệu trong 1 hồ sơ XML nên bạn không thể xử lý result như phần tử XML. Và bạn cần parseFromString để làm điều đó.


Trở lại với công việc chính, theo logic chương trình như trên, chúng ta thêm vào class RichTextEditor 1 thuộc tính có tên là clipBoard :


function RichTextEditor(sID, oContain, sDefaultText, iWidth, iHeight){
this.ID=sID;
this.content=sDefaultText;
this.width=(iWidth>300?iWidth:500);
this.height=(iHeight>80?iHeight:200);
this.clipBoard='';
....

Và phương thức useClipboard được định nghĩa như dưới đây :


RichTextEditor.prototype.useClipboard=function(com mand){
if(isIE){
this.format(command);
}
else{
if(command=='cut'||command=='copy'){
var sel = this.UI.getSelection();
if(sel==''){return;}
var range = sel.getRangeAt(0);
var docFrag = (command=='cut')?range.extractContents():range.clo neContents();
var xmls = new XMLSerializer();
this.clipBoard=xmls.serializeToString(docFrag);
}
else if(command=='paste'){
if(this.clipBoard!=''){
this.format('inserthtml',this.clipBoard);
}
}
}
this.UI.focus();
}

useClipboard kiểm tra xem trình duyệt có phải IE không, nếu là IE thì thực hiện command bình thường. Ngược lại, bắt đầu phân tích command.

Với copy và cut, chúng ta tạo ra Selection


var sel = this.UI.getSelection();

Từ đối tượng Selection này, chúng ta tạo Range bằng phương thức getRangeAt(0). Ở đây, tham số 0 ám chỉ Range đầu tiên trong tập hợp Range.


var range = sel.getRangeAt(0);

Và clone của nó ở dạng documentFragment. Nếu là cut thì sử dụng extractContents, nếu là copy thì sử dụng cloneContents :


var docFrag = (command=='cut')?range.extractContents():range.clo neContents();

Cuối cùng , chúng ta khởi tạo XMLSerializer và chuyển chuỗi vào clipboard của Editor.


var xmls = new XMLSerializer();
this.clipBoard=xmls.serializeToString(docFrag);


Với paste, chúng ta dùng command inserthtml để chèn chuỗi từ clipboard vào editor :


this.format('inserthtml', this.clipBoard);

Thế là vấn đề đã được giải quyết xong. Bây giờ hãy thêm vào toolbar các lệnh Copy, Cut và Paste :


<img id="btnCut" src="cut.gif" title="Cut">
<img id="btnCopy" src="copy.gif" title="Copy">
<img id="btnPaste" src="paste.gif" title="Paste">

Và thêm thiết lập action trong hàm init :


setActionOnButton('btnCut', 'RTE.useClipboard("cut");');
setActionOnButton('btnCopy', 'RTE.useClipboard("copy");');
setActionOnButton('btnPaste', 'RTE.useClipboard("paste");');

Kết quả sẽ như trang demo này :

http://sacroyant.uni.cc/Examples/Editor/V1/rte3.htm


:::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::::::::

* Bổ sung một chút

Phương thức unformat không hoạt động chính xác trên Opera, đã được sửa lại như sau :



var isOp=(navigator.appName=='Opera')?true:false;

RichTextEditor.prototype.unformat=function(){
if(isOp){
var sel = this.UI.getSelection();
this.format('inserthtml', sel);
}
else{
this.format('removeformat');
this.format('unlink');
}
}

Ban biên tập xin cáo lỗi cùng quý độc giả lol

TUAN
07-01-2008, 17:11
Rất ủng hộ tinh thần học tập của Anh em, Tôi không biết là những link này tồn tại được bao lâu, và cũng hơi vi phạm bản quyền một xíu, nhưng thôi, trên tinh thần học hỏi, mình dùng để nguyên cứu mà !
Tôi sưu tập cả một kho sách về JS, ajax, PHP, và chỉ dùng để tra cứu khi cần thiết, học những cuốn nào được cho là hay... và cách sử dụng những thứ có sẵn hiệu quả, tùy biến nó thành của mình. Và công nhận một điều rằng, tôi không bao giờ viết bằng người ta được

http://phamminhtuan.thegioihostfree.com/JS_101_Essential_Tips_Tricks_Hacks.rar
http://phamminhtuan.thegioihostfree.com/Advanced%20JavaScript,%203rd%20Edition.zip
http://phamminhtuan.thegioihostfree.com/JavaScript%20.part1.rar
http://phamminhtuan.thegioihostfree.com/JavaScript%20.part2.rar
http://phamminhtuan.thegioihostfree.com/JavaScript%20.part3.rar
http://phamminhtuan.thegioihostfree.com/JavaScript%20.part4.rar
http://phamminhtuan.thegioihostfree.com/JavaScript%20.part5.rar
Do cái host free chỉ cho dưới 3mb,ngoài ra tài liệu còn nằm ở những trang sau đây, chủ yếu rapidshare.com link
http://avaxsphere.com/
http://katz.cd
....
Nếu có ai thấy phiền phức, sai qui định, delele nó đi, cái user này cũng không phải của tôi, nhưng

pixelart
08-02-2008, 11:19
Cái text editor này sao bác ko thêm màu cho chữ và mấy cái smile vào cho đẹp ^^

sacroyant
11-02-2008, 18:23
Cái text editor này sao bác ko thêm màu cho chữ và mấy cái smile vào cho đẹp ^^

Em đã nói rồi, bài này chỉ hướng dẫn những kỹ thuật căn bản trong việc tạo ra 1 RTE on the web. Phát triển về hình thức là việc của mỗi người :w00t:

sacroyant
28-02-2008, 05:37
Nhúng bộ gõ chữ Việt

Để nhúng bộ gõ chữ Việt, chúng ta có thể sử dụng AVIM. Nó xử lý khá thông minh và hỗ trợ tốt các iframe dạng editable.

Bạn có thể tải AVIM từ website của tác giả : http://hdang.co.uk/

Việc sử dụng khá đơn giản, bạn chỉ cần nhúng file JavaScript có tên là AVIM.js vào trong trang web chứa Editor, nó sẽ làm việc.

Điều duy nhất cần chú ý là nên bỏ chế độ check spell, nó thường làm người sử dụng khó chịu khi gõ các thuật ngữ tin học bằng tiếng Anh. Ví dụ như ở forum này, khi tôi gõ AJAX, nó sẽ thành Ẫ. Rất chuối !

Để loại bỏ chế độ tự fix chính tả, bạn mở AVIM.js, sửa giá trị biến dockspell thành 0, mặc định của nó là 1.

AVIM hỗ trợ 5 kiểu gõ : AUTO, TELEX, VNI, VIQR, VIQR*. Tuy vậy, hiện nay được sử dụng nhiều nhất vẫn là VNI, trong trang demo dưới đây, tôi chỉ sử dụng VNI :

http://sn.iblogger.org/Editor/

http://farm4.static.flickr.com/3068/2297096106_db8af3f757_o.jpg


Post dữ liệu trong Editor với AJAX

Để có thể dùng AJAX gửi nội dung văn bản từ editor lên máy chủ, chúng ta thêm vào 2 hàm sau :


function cod(s){return encodeURIComponent(s);}
function AJAXControl(){
var req=null;
if(window.ActiveXObject){
req=new ActiveXObject("Msxml2.XMLHTTP");
if(!req){
req=new ActiveXObject("Microsoft.XMLHTTP");
}
}
else if(window.XMLHttpRequest){
req=new XMLHttpRequest();
req.overrideMimeType('text/html');
}
return req;
}

Trong Editor của chúng ta đã có phương thức getContent để lấy nội dung văn bản. Bây giờ tôi thêm 2 phương thức khác là getText và doPost. Phương thức getText cho phép lấy toàn bộ text trong văn bản, mà không tính đến mã định dạng. Phương thức doPost làm nhiệm vụ gửi nội dung văn bản có kèm mã HTML định dạng :


RichTextEditor.prototype.getText=function(){
return isIE?this.editor.body.innerText:this.editor.body.t extContent;
}

RichTextEditor.prototype.doPost=function(target){
var content=this.getContent();
if(content==''){
alert("No data to send !");
return;
}
else if(this.getText().length<20){
alert("Message too short !");
return;
}
else{
val='content='+cod(content);
var req=AJAXControl();
if(req!=null&&typeof(req)!=undefined){
req.onreadystatechange =function(){
if(req.readyState==4&&req.status==200){
var response=req.responseText;
//xử lý kết quả trả về
}
req.open("POST", target, true);
req.setRequestHeader("Content-Type","application/x-www-form-urlencoded;");
req.send(val);
}
}
}

Như vậy, phương thức doPost cần 1 tham số là file đích ở trên server sẽ nhận dữ liệu. Vấn đề xem ra khá đơn giản và không cần phải giải thích gì thêm.

Một ví dụ minh họa là phần Thảo luận - Góp ý (http://thuvienvl.uni.cc/?action=discussion) trên Võ lâm văn sĩ giai phẩm quán (http://thuvienvl.uni.cc/?) :

http://thuvienvl.uni.cc/?action=discussion

http://farm4.static.flickr.com/3127/2296331757_90e29cd460.jpg (http://farm4.static.flickr.com/3127/2296331757_0356013a9a_o.jpg)

(Bác nào hiểu rõ về lỗi XSS thì kiểm tra giùm tôi với lol)

Bài hướng dẫn này xin dừng ở đây. Nếu các bạn có thắc mắc gì thêm, xin vui lòng cho biết, tôi sẽ cố gắng trả lời trong thời gian nhanh nhất.

Tạm biệt.

TheHeTre
28-02-2008, 14:35
Cảm ơn bạn. Sẽ cố gắng lĩnh giáo được hết cao chiêu. Rất mong @sacroyant tiếp tục phát huy những bài chất lượng

S_TQV
27-04-2008, 22:10
lam sao de chen mot noi dung html vao dung vi tri con tro trong khung soan thao ma khong dung execCommand.

thanks.

sacroyant
30-04-2008, 00:59
Chào các bạn, Sacroyant tái xuất giang hồ nè :emlaugh::emlaugh:

@ ht83 : mình nghĩ bài viết này đã cung cấp đủ các vấn đề cần thiết cho việc xây dựng 1 RTE rồi mà bạn :w00t:

@ S_TQV : với các editor dạng WYSIWYG, dùng execCommand là giải pháp đơn giản và hiệu quả nhất. Ngoài ra, bạn hoàn toàn có thể tạo ra cơ chế riêng, dựa trên việc chuyển đổi từ mã JS sang HTML. Nhưng con đường đó không thuận tiện chút nào :no:

trinhdiep
07-05-2008, 03:12
vốn không muốn Reply nhưng mà bài quá hay. he, đúng cái mình đang cần gấp. Bí mây hôm nay rồi. Cảm ơn các bạn nhé!

ngocthom96
07-05-2008, 10:21
Cám ơn bạn nhiều lắm nha, bài viết của bạn thật hay, mà bạn cũng thật tốt

Danglvh
09-05-2008, 11:56
<b>cái này mình nhúng vào asp.net dc ko bạn</b>, mình muốn khi post, nó sẽ lấy nội dung bằng c#. Khi đó mình chỉ cần xác định cái ID của cái IFrame chứ cái content đó. hình như nó là editor_UI gì đó, nhưng khi mình viết code để lấy nội dung thì ko dc. Hình như cái đoạn HTML để show Editor nó ko hiện lên mà đc gọi trong javascript, nên khi mình thực hiện câu lệnh string postcontent = Page.Request.Params["editor__UI"] trong C# thì ko dc. Đã tìm cách mấy bửa nay rồi ko mà ko. Mong bạn giúp mình tìm ra giải pháp thích hợp, thanks bạn!

à, mình có gặp một bug này nữa. Sao có lúc mình chạy cái editor trên FF, thì trình duyệt nó disable thanh trược đi và cũng ko dùng chức năng scroll trên chuột để trượt lên xuống dc luôn.

thamtung
19-05-2008, 18:22
hay thật , cho tui tham gia với ! viết tiếp đi anh em . Cảm ơn các bác ,

trinhdiep
03-06-2008, 08:01
<b>cái này mình nhúng vào asp.net dc ko bạn</b>, mình muốn khi post, nó sẽ lấy nội dung bằng c#...

Có nhiều cách mà bác, tớ nghĩ đơn giản nhất là thêm một trường hidden vào ví dụ:
<INPUT id="myfield" type="hidden" value="blah" runat="server">
dung Client Click Button để dưa html của iframe vào myfield; trên server có thể dùng C# để lấy dữ liệu từ myfield bình thường;

hoặc là cho cái iframe đó thêm thuộc tính (runat="server") nữa là có thể truy cập trực tiếp bằng C# rồi. Tất nhiên cách này thì bác phải tạo iframe bằng ASP.NET

Vế sau bác hỏi thì tùy trình duyệt sử dụng mà style hơi khác, bác kiểm tra lại style xem nó có được hỗ trợ của FF không. tớ thấy tất cả các Editor loại nè đều bị hạn chế bởi trình duyệt. vì thế nên bác cần kiểm tra và bổ sung cho từng trình duyệt muốn sử dụng
Ha,sorry, tớ chưa thử nên sai gì thì thông cảm cho tớ

kokoro2442
06-06-2008, 18:32
Ai có thể giải thích cho em cái nè là cái gì hông
document.getElementById(".....").style.display = "....."

thanks

sacroyant
07-06-2008, 11:03
Ai có thể giải thích cho em cái nè là cái gì hông
document.getElementById(".....").style.display = "....."

thanks

Nó điều khiển việc hiển thị hay biến mất của 1 phần tử trên trang.

Ví dụ ta có 1 phần tử div được gán id là "oDiv" :

<div id="oDiv"></div>

Khi đó dòng mã sau sẽ làm ẩn nó đi :

document.getElementById("oDiv").style.display = "none" ;

Và ngược lại, dòng mã sau sẽ làm nó hiện lên :


document.getElementById("oDiv").style.display = "inline" ;

:w00t:

kokoro2442
08-06-2008, 08:24
Cảm ơn bác rất nhiêu.
Bác có tài liệu về mấy cái này không. Hoặc bác biết trang nào giới thiệu vê mấy cái lệnh này chỉ cho em với.

Thanks

sacroyant
09-06-2008, 08:54
Cảm ơn bác rất nhiêu.
Bác có tài liệu về mấy cái này không. Hoặc bác biết trang nào giới thiệu vê mấy cái lệnh này chỉ cho em với.

Thanks

Em có mấy triệu trang, không biết đưa bác xem cái nào :w00t:

http://www.google.com/search?q=javascript+dom

WanderingRiver
11-07-2008, 04:12
Cám ơn bác sacroyant rất nhiều. Em cũng đã làm được rồi nhưng em vẫn chưa biết dữ liệu được lấy từ bàn phím vào iframe rồi sẽ sử lý tiếp thế nào nữa. nếu em để nó vào một form thì sẽ phải lấy dữ liệu như thế nào. Một lần nữa xin cám ơn bác :D.

sacroyant
13-07-2008, 11:03
Cám ơn bác sacroyant rất nhiều. Em cũng đã làm được rồi nhưng em vẫn chưa biết dữ liệu được lấy từ bàn phím vào iframe rồi sẽ sử lý tiếp thế nào nữa. nếu em để nó vào một form thì sẽ phải lấy dữ liệu như thế nào. Một lần nữa xin cám ơn bác :D.

Mấy hôm nay vẫn ghé mà không để ý có bạn hỏi, sorry.

Ở phần này (http://www.ddth.com/showthread.php?p=978864#post978864) mình đã trình bày các phương thức của Editor, bao gồm getContent. Đó là phương thức dùng để lấy nội dung trong Editor.

Có nhiều cách post nội dung này lên máy chủ. Chẳng hạn bạn dùng 1 input ẩn, khi submit form thì gọi 1 hàm javascript có nhiệm vụ :

- lấy nội dung trong editor bằng getContent
- chuyển nội dung ấy vào input ẩn
- thực thi các kiểm tra khác về dữ liệu nhập nếu muốn.
- submit form như bình thường.

Khi đó, ở server, nếu bạn viết mã bằng PHP, và tên thẻ input ẩn là "data" chẳng hạn, thì nội dung gửi lên được ghi nhận bằng $_POST["data"]

Trong trường hợp dùng AJAX, bạn không cần tạo input ẩn.

WanderingRiver
15-07-2008, 07:49
cách lấy nội dung trong editor thì em đã hiểu nhưng em vẫn chưa biết truyền nội dung đó nên một input ẩn như thế nào :D. Em sẽ phải tạo một input type hidden nhưng value của nó em sẽ phải làm sao :D. Mong anh thông cảm em mới học java script nên chưa rành lắm :D.

sacroyant
15-07-2008, 08:13
cách lấy nội dung trong editor thì em đã hiểu nhưng em vẫn chưa biết truyền nội dung đó nên một input ẩn như thế nào :D. Em sẽ phải tạo một input type hidden nhưng value của nó em sẽ phải làm sao :D. Mong anh thông cảm em mới học java script nên chưa rành lắm :D.

Giả sử chúng ta đã có 1 editor trên trang như trong các bài hướng dẫn. Bây giờ để post nội dung trong editor lên 1 file xử lý send.php theo cách truyền thống. Chúng ta tạo 1 form :


<form name="f" action="send.php" method="post">
<input type="hidden" name="data" value="">
<input type="button" value="Send" onclick="doSend();">
</form>

Và đây là hàm doSend :


funcition doSend(){
var content=RTE.getContent();
// kiểm tra dữ liệu nếu muốn :
//..............................

//gán giá trị trong editor vào hidden input :
document.f.data.value=content;

//và submit form :
document.f.submit();
}

Cuối cùng là send.php, ngại gì mà không kiểm tra nhỉ :)


<?
$content=$_POST['data'];
echo $content;
?>


- Trong cấu trúc của hồ sơ HTML , form trên không nhất thiết phải bao lấy phần editor.
- Nếu dùng iframe ẩn, bạn chỉ định target cho form. Cách này phù hợp hơn cả khi làm việc với các WYSIWYG.
- Nếu truyền dữ liệu qua XMLHttpRequest, bạn không cần tạo form này nếu không có các trường khác phải gửi đi. Đây là cách tớ thích dùng nhất.

Cảm ơn bạn đã quan tâm đến chủ đề này :)

WanderingRiver
15-07-2008, 21:06
cám ơn anh rất nhiều, nhưng khi em thêm hàm dosend vào thì hình như thuộc tình designMode không còn hiệu lực nữa thì phải :(.

sacroyant
15-07-2008, 22:13
cám ơn anh rất nhiều, nhưng khi em thêm hàm dosend vào thì hình như thuộc tình designMode không còn hiệu lực nữa thì phải :(.

Chẳng ảnh hưởng gì đâu bạn. Có lẽ bạn nhầm lẫn ở chỗ nào đó thôi. designMode là thuộc tính của iframe mà chúng ta dùng làm nền soạn thảo. Còn doSend chạy ở main window mà :emlaugh:

WanderingRiver
16-07-2008, 13:28
cám ơn anh rất nhiều em đã làm được chỉ là một sai sót nhỏ khi em đặt tên hàm trùng nhau :D. Thanks anh rất nhiều vì một đề tài rất hay và cám ơn anh vì anh rất tận tình trả lời câu hỏi của thành viên :D.

sacroyant
17-07-2008, 19:40
cám ơn anh rất nhiều em đã làm được chỉ là một sai sót nhỏ khi em đặt tên hàm trùng nhau :D. Thanks anh rất nhiều vì một đề tài rất hay và cám ơn anh vì anh rất tận tình trả lời câu hỏi của thành viên :D.

Chúc mừng bạn. Mình đang soạn phần 2 của topic này, có gì bạn theo dõi tiếp nhé :w00t:

Còn việc mà bạn pm thì cho mình xin lỗi, trước giờ không khoái chơi YM, ít người lôi kéo được mình đăng nhập nick chát lắm :emlaugh:

sacroyant
22-07-2008, 01:22
Xem tại đây...

http://www.ddth.com/showthread.php?p=1230110#post1230110

3do
22-07-2008, 04:40
http://markitup.jaysalvat.com/examples/

cái này cũng khá hay, viết bằng jQuery. Có khả năng tuỳ biến cao

Cool_rain
31-07-2008, 01:05
Đang nói là tự xây dựng mà bác lại lôi cái FW có sẵn ra, nhạt quá.

ha_con_bk
12-08-2008, 15:34
@sacroyant: bạn chèn thêm Yahoo eco bằng hàm nào thế nhỉ ?
mình có xem mã nguồn bạn share hoàn chỉnh nhưng chưa tìm ra.
Thankz.

sacroyant
12-08-2008, 17:47
@sacroyant: bạn chèn thêm Yahoo eco bằng hàm nào thế nhỉ ?
mình có xem mã nguồn bạn share hoàn chỉnh nhưng chưa tìm ra.
Thankz.

Để đưa emoticon của Yahoo! IM vào editor, mình tạo 1 mảng đa chiều :


this.emoticons=[
['happy',':)','1.gif'],
['sad',':(','2.gif'],
['rose','@};-','53.gif'],
['coffee','~O)','57.gif'],
['batting eyelashes',';;)','5.gif'],
['big hug','>:D<','6.gif'],
['confused',':-/','7.gif'],
['love struck',':x','8.gif'],
['blushing',':">','9.gif'],
['tongue',':P','10.gif'],
['surprise',':-O','13.gif'],
['cool','B-)','16.gif'],
['crying',':((','20.gif'],
['laughing',':))','21.gif'],
['straight face',':|','22.gif'],
['don\'t tell anyone',':-$','32.gif'],
['yawn','(:|','37.gif'],
['thinking',':-?','39.gif'],
['d\'oh','#-o','40.gif'],
['applause','=D>','41.gif'],
['angel','O:)','25.gif'],
['daydreaming','8->','105.gif'],
['kiss',':-*','11.gif'],
['angry','X(','14.gif'],
['worried',':-S','17.gif'],
['waiting',':-w','45.gif'],
['I don\'t know',':-??','106.gif'],
['shame on you','[-X','68.gif'],
['whistling',':-"','65.gif'],
['praying','[-O<','63.gif'],
['winking',' ;)','3.gif'],
['big grin',':D','4.gif']
];

Như vậy this.emoticons[n][0] là ý nghĩa của biểu tượng, hiển thị dạng title khi di chuột lên. this.emoticons[n][1] là ký tự viết tắt của emoticon. Và this.emoticons[n][2] là tên file hình (mà Yahoo! đặt cho).

Sau đó mình viết 1 phương thức có tên là osl (nghĩa là Open Smiley List ấy mà :)) để duyệt qua các chiều của mảng trên và tạo thành 1 bảng các hình biểu tượng :


this.osl=function(){
var s='<table border="0" width="120" height="100%" cellpadding="0" cellspacing="0">';
var h=0,k=0;
for(var i=0;i<8;i++){
s+='<tr height="20" >';
h=k;
for(var j=0;j<4;j++){
if(this.emoticons[(h+j)]){
s+='<td align="center" width="30" height="25" title="'+this.emoticons[(h+j)][0]+'"><img src="'+this.emoticonPath+this.emoticons[(h+j)][2]+'" onclick="'+this.is+'.insertImage(\''+this.emoticonPath+this .emoticons[(h+j)][2]+'\');"></td>';
}
else{
s+='<td>&nbsp;</td>';
}
k++;
}
s+='</tr>';
}
s+='</table>';
this.sm('btnEmoticon',s);
}

this.sm (sm = Set Menu)là phương thức dùng để gán 1 chuỗi vào thuộc tính submenu.

this.is (is = Instance) là biến nội tại giữ vai trò hiện thể của Editor.

this.emoticonPath là thuộc tính có giá trị chỉ định đường dẫn đến thư mục chứa các hình ảnh.

Khi click vào 1 emoticon thì gọi phương thức insertImage với tham số là URL của file hình :


onclick="'+this.is+'.insertImage(\''+this.emoticonPath+this .emoticons[(h+j)][2]+'\');"

Phương thức insertImage như sau :


this.insertImage=function(url){
this.cm();
this.UI.focus();
var aLink=(url==null)?prompt('Enter or paste a URL :', ''):url;
if(aLink){
this.fmt('InsertImage', aLink);
}
}

trong đó :

- this.cm() : đóng các menu nếu có (cm = Close Menu)

- this.UI.focus() : focus vào vùng soạn thảo.

Nếu không có tham số truyền vào cho phương thức, nó sẽ hiển thị hộp thoại prompt để nhận 1 đường dẫn cho hình ảnh muốn chèn. Nếu có tham số truyền vào, giá trị tham số sẽ được gán cho biến cục bộ aLink (đây là trường hợp chèn emoticons).

ha_con_bk
12-08-2008, 17:50
many thankz, mình làm được rồi, đang tìm tài liệu về cái này, tìm đúng bài
cho mình hỏi sacroyant không tích hợp các chức năng như chèn bảng, đường kẻ ngang ... vào luôn.
Mình đọc trên w3 thấy nói về HTML Dom mà khó hiểu quá :D

sacroyant
12-08-2008, 18:01
many thankz, mình làm được rồi, đang tìm tài liệu về cái này, tìm đúng bài
cho mình hỏi sacroyant không tích hợp các chức năng như chèn bảng, đường kẻ ngang ... vào luôn.
Mình đọc trên w3 thấy nói về HTML Dom mà khó hiểu quá :D

Thấy chừng đó cũng đủ sài rồi :w00t:

Nhìn cái này giống Gmail phết :boxing::ohmy:


http://img398.imageshack.us/img398/3781/36441823bh8.jpg

ha_con_bk
13-08-2008, 13:21
site đó là thư viện sách truyện của bác ???
Bác có thể hướng dẫn chèn table hem ?
đang kết cái này mà hok có tài liệu, đọc của bác thấy dễ hiểu hơn ;))

sacroyant
13-08-2008, 20:42
site đó là thư viện sách truyện của bác ???
Bác có thể hướng dẫn chèn table hem ?
đang kết cái này mà hok có tài liệu, đọc của bác thấy dễ hiểu hơn ;))

Vâng, mấy cuốn hay hay tớ để đó coi dần :w00t:

Nếu bạn đã thành thạo HTML thì có khó gì trong việc nhúng 1 bảng vào Editor ? ! Đó chẳng qua là chèn 1 chuỗi HTML vào thôi mà :ohmy:

Hàm sau sẽ sinh mã HTML cho 1 bảng với số hàng và cột biết trước.


function createTable(rows, cols){
var s='<table border="1" cellpadding="4" cellspacing="0">';
for(var i=0;i<rows;i++){
s+='<tr>';
for(var j=0;j<cols;j++){
s+='<td width="100"></td>';
}
s+='</tr>';
}
s+='</table>';
return s;
}

Bạn có thể thêm các tham số khác để cho phép người dùng tạo ra các table theo đúng ý họ muốn : width, height, border, cellpadding...

Chèn chuỗi vào vị trí con trỏ trong Editor rất đơn giản. Với IE, bạn tạo ra 1 đối tượng Range và sử dụng phương thức pasteHTML của đối tượng này. Với các trình duyệt chuẩn, bạn dùng command ImsertHTML.

Chúng ta có thể thêm 1 method vào class Editor để chuyên trách nhiệm vụ nhúng các chuỗi, như sau :


Editor.prototype.insertStr=function(str){
if(isIE){
var aRange=this.ed.selection.createRange();
aRange.select();
aRange.pasteHTML(str);
}
else{
this.fmt('inserthtml',str);
}
}

Kết nối các điểm trên lại, bạn sẽ thấy cách tạo bảng.

Ví dụ, mình viết 1 method insertTable đơn giản như dưới đây :


Editor.prototype.insertTable=function(){
var r=prompt('Enter number of rows : ','');
if(!r||isNaN(r)||r<1){return;}
var c=prompt('Enter number of cols : ','');
if(!c||isNaN(c)||c<1){return;}

this.insertStr(createTable(r, c));
}

Cách làm khái quát là như thế đó bạn :w00t::innocent:

[=========> Bổ sung bài viết <=========]

Đã thêm vào ví dụ :

http://lovepm.uni.cc/Examples/Editor/

ha_con_bk
26-08-2008, 16:45
hem, đang chờ đợi phần 2 của bác :D

zoejoe
29-08-2008, 05:37
Đã chính thức kết thúc roài, phần 2 nằm ở 1 topic đâu đó trên dd này nè, search thử xem

mhungou04
01-10-2008, 02:00
Cái Text của bạn làm hay lắm Nhưng sử dụng nó thế nào để post dữ liệu thế

songcon2
02-10-2008, 10:42
Mình cũng đang cần xây dựng 1 cái WYSIWUG như thế này. Thank sacroyant nhiều! ^_^

wenddy
02-10-2008, 14:23
Rich Text Editor là gì? có phải muốn làm cho mình một Rich Text Editor thì phải có một trang web của riêng mình? bạn nói về Rich Text Editor nghe rất hấp dẫn nhưng bạn nói quá chung chung và không có "đầu" nên mình không biết vào đâu để làm 1 Rich Text Editor? bạn có thể chỉ rỏ hơn được không?

whitepenguin
28-11-2008, 12:35
Cho em hỏi tại sao mỗi khi xuống dòng nó lại cách ra 1 hàng thế , có cak nào làm liền lại hok

sacroyant
03-12-2008, 17:36
Cho em hỏi tại sao mỗi khi xuống dòng nó lại cách ra 1 hàng thế , có cak nào làm liền lại hok

Trong IE, khi nhấn Enter nó sẽ tạo ra 1 new paragraph. Tạm khắc phục bằng cách nhấn Shift + Enter. Tớ sẽ tìm hiểu thêm để loại bỏ hiện tượng này. Gmail không bị như vậy nên chắc là có phương pháp.

pleiku83
04-12-2008, 16:05
Hey hey... Trước hết cảm ơn bạn Sacroyant nhiều.
Tui đang nghĩ tới 1 vấn đề ko biết tìm ở đâu: Tui Upload tài liệu (doc, pdf..) lên 1 folder trên WebServer, ý tui bây giờ trong khi viết bài, tui muốn tạo hyperlink đến 1 file .doc thì làm sao nhỉ? Cái nút Hyperlink yêu cầu phải gõ URL, nhưng có cách nào khi mở cửa sổ Hyperlink lên thì nó cho Browser các file trên chính Server ko nhỉ?
Giống như nó tạo ra tag: <a href="../tailieu/abc.doc">Download</a>
tóm lại là nó duyệt và tạo link đến 1 file trên chính server? Bạn trả lời giúp tui nhé. Thanks.

sacroyant
04-12-2008, 19:07
Hey hey... Trước hết cảm ơn bạn Sacroyant nhiều.
Tui đang nghĩ tới 1 vấn đề ko biết tìm ở đâu: Tui Upload tài liệu (doc, pdf..) lên 1 folder trên WebServer, ý tui bây giờ trong khi viết bài, tui muốn tạo hyperlink đến 1 file .doc thì làm sao nhỉ? Cái nút Hyperlink yêu cầu phải gõ URL, nhưng có cách nào khi mở cửa sổ Hyperlink lên thì nó cho Browser các file trên chính Server ko nhỉ?
Giống như nó tạo ra tag: <a href="../tailieu/abc.doc">Download</a>
tóm lại là nó duyệt và tạo link đến 1 file trên chính server? Bạn trả lời giúp tui nhé. Thanks.

Cái này làm rất đơn giản. Ở phía client, bạn tạo ra 1 cửa sổ giả lập hộp thoại Open. Cửa sổ này có 1 vùng trống để liệt kê danh sách các file trong thư mục, phía dưới vùng liệt kê là 2 nút Open và Cancel.

Giả sử dùng PHP, bạn viết 1 file đặt tên là list.php chẳng hạn, file này có nhiệm vụ duyệt thư mục và trả về danh sách files bên trong. Dùng các lệnh dir, filesize, filetype... để lấy thông tin về các file. Dữ liệu gửi xuống client có thể là XML, text, hoặc JSON tùy bạn.

Cuối cùng, bạn dùng AJAX kết nối 2 phần việc lại với nhau.

Tóm lại chỉ cần mấy bước ngắn :


Mở hộp thoại giả lập trên giao diện người dùng
Gọi file list.php thực thi qua AJAX method.
Xử lý dữ liệu nhận về.
Gán kết quả phân tích vào vùng liệt kê.


Bước 1 và 2 có thể đổi chỗ cho nhau.

pleiku83
05-12-2008, 14:41
Tui hình dung được thủ tục đó, nhưng tui cũng chỉ mới amateur, đang phải phân tích cái source có sẵn chứ chưa biết nhiều và chính xác câu lệnh ntn. Đại khái tui xem qua cái Editor.js có sẵn, nó có đoạn khi "createlink" thì thi hành cái "execCommand(a,b)", cửa sổ Hyperlink mở ra dường như là kiểu mặc định luôn như vậy, tui ko biết can thiệp vô chỗ nào cả.
Bạn có thể chỉ chi tiết một chút được ko:
- Dùng lệnh gì (code đầy đủ) để mở cửa sổ Open.
- File list.php nội dung ntn? Tui dùng asp nhưng bạn có thể cho tui nội dung php cũng được, ko khác mấy.
- Sau khi duyệt file (trên Server ấy nhé, chứ ko phải Browser đến Computer đang dùng) nút OK submit cái gì để ghi hyperlink ra vùng text.
Tóm lại tui nghĩ nó cũng nho nhỏ, bạn giúp tui code đầy đủ để đạt kết quả được ko? Thanks a lot.

[=========> Bổ sung bài viết <=========]

Mà tại sao tui thấy mọi người ít bàn về vụ này nhỉ? VD trong forum i4vn.com có bộ Editor có nút "File đính kèm" để tạo link download file. Nếu ko có nút này, vậy mấy trang web như: http://danang.vnn.vn/tenmien/vanban.asp
hoặc tui muốn tạo 1 trang "báo cáo tài chính" trong đó vừa có text, vừa có link download file đính kèm thì làm sao?
Chẳng nhẽ khi dùng CMS soạn thảo bài viết phải gõ tay path đến folder chứa file, rồi gõ tên file vô dòng URL Hyperlink?
(Mình dùng ASP, ko có CMS như Joomla)

sacroyant
05-12-2008, 17:13
Cửa sổ mà tớ nói đến chỉ là cái khung để chúng ta trình bày các files trong folder mà người dùng duyệt tới. Nó không liên quan gì đến command hyperlink của editor.

Làm một cửa sổ giả lập thì rất đơn giản, bạn xem 1 ví dụ trên trang chủ của tớ qua hình này :


http://e.imagehost.org/0468/1_7.png (http://sacroyant.googlepages.com/index.htm?nl=vi)

Class để mở ra cửa sổ soạn thảo như dưới đây :



function Dialog(id, width, height, content, title, icon){
this.id=id;
this.width=width;this.height=height;
this.title=title;this.content=content;
this.icon=icon||'';
this.iconPath=editor.iconPath||'';
this.open=function(closeFunc){
if(editor&&isIE&&editor.ed){
editor.ed.focus();
bookmark = document.selection.createRange();
}
var s='';
var el=rel(this.id).style;
el.position='absolute';
el.width=this.width+'px';
el.height=this.height+'px';

gWS();
if(this.id=='box'){waiting();}
el.top=parseInt((this.height<winsize.h)?Math.round((winsize.h-this.height)/2):0)+'px';
el.left=parseInt((this.width<winsize.w)?Math.round((winsize.w-this.width)/2):0) +'px';
s+='<table width="100%" height="100%" cellpadding="0" cellspacing="0">';
s+='<tr height="20" bgcolor="#4131af" class="wintitle">';
s+='<td id="titleBar_'+this.id+'" width="'+(this.width-20)+'" onmousedown="startDrag(\''+this.id+'\',\'#9999ff\');">'+((this.icon!='')?('<img src="'+this.icon+'" width="15" height="16" hspace="2">'):'')+'&nbsp; '+this.title+'</td>';
s+='<td width="20" align="center" title="Close" onclick="'+closeFunc+';"><img src="'+this.iconPath+'close.gif"></td>';
s+='</tr><tr height="'+(this.height-20)+'">';
s+='<td valign="top" colspan="2">';
s+=this.content;
s+='</td></tr></table>';

show(this.id);gTxt(this.id, s);
rel(this.id).style.position='absolute';
rel(this.id).style.zIndex='202';
setOpacity(this.id, 98);
}
this.close=function(){
hide(this.id);hide("transit");
}
this.changeStatus=function(){
if(this.status==0){this.open();}
else{this.close();}
}
}

Bạn có thể xem đầy đủ mã nguồn khi View Source.

Trong trường hợp của bạn, cái mà chúng ta trình bày không phải là 1 editor mà giống như thế này :


http://e.imagehost.org/0785/2_2.png

Tớ không đọc kỹ phần trước của bạn. Bạn muốn tạo link chứ không phải mở file được chọn, vậy thay vì Open sẽ là Create Link. Muốn nó làm việc như thế nào là ở bước phân tích dữ liệu trả về bởi list.php. Ví dụ 1 file bất kỳ trong list sẽ có code dạng này :

<span id="f_XYZ" onclick="selectMe('fileName')">File XYZ</span>

selectMe là hàm gửi giá trị tham số truyền vào đến 1 biến tạm nào đó. Và khi nhấn CreateLink, nó sẽ gán đường dẫn vào command thực thi tương ứng với việc tạo liên kết. Đây chỉ là 1 cách.


Nếu bạn đã hình dung được các bước thì nên cố gắng tìm hiểu và tự giải quyết từng bước sẽ tốt hơn là nhờ ai đó làm giúp hoàn toàn.

ngoc_viet08
14-12-2008, 18:04
hay quá , mình cũng đang cần học cách tạo đoạn soạn văn bản thế này .
nhưng bạn có thể nói qua cách thức làm cái đoạn gửi bài này ko .
đầu tiên phải tạo ra 1 form gửi bài thế này .
như bạn là biến đổi dữ liệu trực tiếp . trong các forum thì họ tạo ra các thẻ ví dụ như .
nếu dùng biến đổi dữ liệu trực tiếp . thì khi gửi bài , nó gửi vào csdl rồi load ra thì đoạn văn bản có giống như lúc mình gửi hay là nó thành đoạn văn bình thường ko định dạng ? phải làm thế nào nhỉ
còn nếu dùng các thẻ như thế thì người ta làm sao nhỉ . lưu vậy luôn vào csdl rồi lúc load thì thay đổi đoạn văn bản, chuyển các thẻ tự biên về đúng cấu trúc các thẻ html à ?
bạn nói rõ cho mình nhé . thank .
à ngoài ra muốn chèn thêm các nút file nhạc , video , flv gì đó thì làm sao nhỉ ...

sacroyant
21-12-2008, 00:28
@ ngoc_viet08 : với những cái gọi là WYSIWYG Editor thì văn bản lưu trong database thường sẽ có dạng HTML. Bạn cũng có thể lập trình để nhúng các thành phần không phải HTML vào nội dung. Chẳng hạn như mình đã tạo thẻ để đánh dấu các đoạn code muốn trình bày theo cách riêng. Nhúng Flash cũng tương tự vậy thôi.

phuongdung1
25-12-2008, 09:41
Tớ đã làm được Editor rồi, nhưng khi đưa text vào Editor rồi Submit.
Khi text ít thì tớ Submit được nhưng khi text dài thì khi Submit hiện ra 1 bảng thông báo Security Warning như thế này:
" The current Web page is trying to open a site in Internet. Do you want to allow this? "
Có 2 nút YES và NO
Và phía dưới có 1 Warning:
" Warning: allowing this can expose your computer to security riks.
If you don't trust the curent Web page, choose NO "
Nhưng tớ nhấn YES nó vẫn ko Submit dc, trang web đứng yên.
Tớ không biết giải quyết thế nào. Mong mọi người giúp đỡ. Tớ đang rất cần cái này vì tớ đang làm 1 module Tin tức.

[=========> Bổ sung bài viết <=========]

Tớ đang làm bằng JSP nhé. Mong được sự giúp đỡ.

sacroyant
25-12-2008, 21:38
Tớ đã làm được Editor rồi, nhưng khi đưa text vào Editor rồi Submit.
Khi text ít thì tớ Submit được nhưng khi text dài thì khi Submit hiện ra 1 bảng thông báo Security Warning như thế này:
" The current Web page is trying to open a site in Internet. Do you want to allow this? "
Có 2 nút YES và NO
Và phía dưới có 1 Warning:
" Warning: allowing this can expose your computer to security riks.
If you don't trust the curent Web page, choose NO "
Nhưng tớ nhấn YES nó vẫn ko Submit dc, trang web đứng yên.
Tớ không biết giải quyết thế nào. Mong mọi người giúp đỡ. Tớ đang rất cần cái này vì tớ đang làm 1 module Tin tức.

[=========> Bổ sung bài viết <=========]

Tớ đang làm bằng JSP nhé. Mong được sự giúp đỡ.

Bác nào có kinh nghiệm về JSP xem giúp bạn ấy với nhỉ. Tớ chưa từng chơi với em JSP này ! Cũng có thể do cách cấu hình trình duyệt chăng ? Bạn dùng web browser nào khi nhận warning đó ?

phuongdung1
26-12-2008, 09:11
Tớ đang viết chương trình trên NetBeans IDE 6.1 chạy với Tomcat 6.0 dùng IE 6 đó bạn.
Các bạn giúp mình với.

sacroyant
26-12-2008, 12:29
Có thể do bạn chạy thử script trên localhost nên IE nó báo vậy để hạn chế khai thác lỗi Local Web Pages. Bạn cấu hình lại IE, thiết lập độ tin cậy của trang chứa script thành Miscellaneous xem sao.

Internet Options/Security/Trusted Sites/Custom Level/Miscellaneous

phuongdung1
29-12-2008, 09:01
Tớ đã làm như bạn nói rồi mà vẫn ko được.
Hic, giúp tớ với!

ngoc_viet08
09-01-2009, 09:56
Định dạng văn bản tại chỗ :

bold : in đậm text
fontname : font chữ, vValue :tên font. VD : arial, verdana...
fontsize : khổ chữ, vValue : các số từ 1 đến 7.
forecolor : màu chữ. vValue : chuỗi tên hoặc mã màu. VD : #0000ff, navy...
hilitecolor : màu nền (1). vValue : chuỗi tên hoặc mã màu. VD : #0000ff, navy...
italic : làm nghiêng text
subscript : text thấp xuống so với bình thường
superscript : đẩy text lên cao hơn bình thường
underline : gạch dưới text

Định dạng khối văn bản :

heading : Định dạng cho một tiêu đề. vValue : <h1>, <h2>, <h3>, <h4>, <h5>, <h6>.
indent : cho khối văn bản lui vào 1 tab
insertorderedlist : liệt kê theo số thứ tự
insertunorderedlist : liệt kê không đánh số.
justifycenter : căn giữa
justifyfull : dàn đều 2 biên
justifyleft : căn trái
justifyright : căn phải
outdent : cho khối văn bản lui ra 1 tab

Các command khác :

createlink : tạo liên kết. vValue : chuỗi URL
delete : xóa phần selection
inserthorizontalrule : chèn vào 1 phần tử <hr>
inserthtml : chèn vào 1 chuỗi HTML (2)
insertimage : chèn hình ảnh. vValue : đường dẫn đến file ảnh.
removeformat : loại bỏ các định dạng ở phần selection.
unlink : loại bỏ liên kết ở phần selection.

Các command điều khiển editor :

undo : khôi phục lại tình trạng trước khi có 1 thay đổi được ghi nhận (3)
redo : khôi phục lại tình trạng trước khi undo 1 bước.
selectall : chọn toàn bộ nội dung editor.

Danh sách trên chưa đầy đủ, nhưng là những gì cơ bản nhất cho 1 trình soạn thảo văn bản. Chúng là các commands nhận được sự hỗ trợ chung của nhiều trình duyệt.

Nhắc lại cú pháp của execCommand :

editableDocument.execCommand(sCommand [, bUserInterface] [, vValue])

Trong đó :

editableDocument : tên biến tham chiếu đến phần tử document của đối tượng iframe được dùng để giả lập khung soạn thảo.
sCommand : chuỗi tên command. Không phân biệt hoa - thường.
bUserInterface : biến tùy chọn hiển thị các DialogBox. Luôn thiết lập là false để tránh lỗi trong Mozilla và Opera.
vValue : giá trị cho command. Nếu command không cần chỉ định giá trị, sử dụng null.

Thông thường vValue là 1 chuỗi, ngoại trừ giá trị cho kích thước chữ có thể để dạng interger, nhưng nói chung vẫn nên đưa về kiểu string.

* Chú thích :


Với IE, cần thay bằng command backcolor.
Chỉ duy nhất Mozilla hỗ trợ command này. Với IE, có thể dùng các command cụ thể cho từng đối tượng muốn chèn, như : InsertInputButton, InsertTextArea, InsertMarquee... Xem thêm tại đây (http://msdn2.microsoft.com/en-us/library/ms533049%28VS.85%29.aspx).
Các thay đổi được ghi nhận có thể là bất cứ hành động nào làm khác đi nội dung vốn có trong Editor, chẳng hạn như việc gõ vào, xóa đi, hay đổi màu 1 ký tự... Undo và Redo chỉ làm việc hoàn hảo trong Mozilla.


thanks về mấy cái command rất hay này . tuy nhiên bạn có thể giới thiệu trọn bộ cho mình về tất cả các command , hay có tài liệu đầy đủ cũng được ko ?
chứ biết được mấy cái này rồi mà giờ muốn viết thêm , phát triển thêm cũng chịu vì ko biết mấy cái command khác ở đâu . thanks
ví dụ như chèn media , chèn flash ,chèn hình ảnh chung line với hình hoặc chữ bao quanh hình...thì làm sao ??

sacroyant
10-01-2009, 22:31
thanks về mấy cái command rất hay này . tuy nhiên bạn có thể giới thiệu trọn bộ cho mình về tất cả các command , hay có tài liệu đầy đủ cũng được ko ?
chứ biết được mấy cái này rồi mà giờ muốn viết thêm , phát triển thêm cũng chịu vì ko biết mấy cái command khác ở đâu . thanks
ví dụ như chèn media , chèn flash ,chèn hình ảnh chung line với hình hoặc chữ bao quanh hình...thì làm sao ??


Đây là những Command Identifiers được hỗ trợ bởi IE :

http://msdn.microsoft.com/en-us/library/ms533049(VS.85).aspx

Còn dưới này là bản chỉ dẫn xây dựng RTF Editor khá cụ thể của Mozilla, kèm theo phần so sánh sự khác biệt giữa các Command Identifiers trên Firefox và IE.

https://developer.mozilla.org/en/Rich-Text_Editing_in_Mozilla

ngoc_viet08
11-01-2009, 00:36
thanks bạn sacroyant nhiều nha . để mình tìm hiểu thêm .
forum mình ko có mấy nút bbcode nhỉ ?

thuyduongcd
03-02-2009, 11:15
Còn một điều khá thú vị nữa mà chưa thấy bàn tới đó là xác định trạng thái của một đoạn text để thay đổi trạng thái nút nhấn tương ứng. Chẳng hạn như trình soạn thảo của google khi di chuyển con trỏ vào vị trí chuỗi in đậm thì nút bold sẽ lõm xuống, di chuyển ra ngoài thì nó sẽ nổi lên

ngoc_viet08
18-02-2009, 09:27
execCommand => thực hiện 1 lệnh command
queryCommandEnabled => trạng thái các câu lệnh command (bật / tắt )
queryCommandIndeterm => ???
queryCommandState => trạng thái của 1 command ???
queryCommandSupported => command này trình duyệt có được hỗ trợ ??
queryCommandValue => giá trị của command ???
bạn có thể giải thích rõ hơn về các cái này ko .
với state thì để kiểm tra 1 đoạn văn bản đã được áp dụng command chưa để làm như bạn thuyhuongcd nói nhỉ ?

còn command createlink mình thấy ko hoạt động . cả trên demo của bác chủ topic cũng vậy . khi tạo ra 1 link thì chả thấy nó đâu .

một điều e băn khoăn nữa là cái RTE này dùng để tiện lợi cho việc soạn bài gửi lên website . nhưng có vẻ nó ko mạnh lắm thì phải . ví dụ muốn tạo 1 hình ảnh và chỉ lên nó có chữ như thuộc tính Art của nó . hay tạo 1 link đến 1 địa chỉ và link đó được ghi bằng 1 tên khác như " my homepage " cũng ko bik làm sao
:D các bạn có thể giúp mình ko ?

[=========> Bổ sung bài viết <=========]

ờ . hóa ra xài addlink là nó biến đoạn đang chọn thành cái link .cái này mình mới biết.
mình cần hỏi 1 vài thứ như :
- trong RTE của các forum . có mục chọn màu sắc cho text . khi nhấp vào biểu tượng của nó thì cho ra 1 bảng màu và chọn màu . cái đó mình phải dùng js để viết à ?
- làm sao để thiết lập 1 hình ảnh nằm riêng 1 dòng hay chữ sẽ nằm bao quanh hình ảnh đó .
mong các bạn giúp cho ...

trinhdiep
22-02-2009, 15:06
"- trong RTE của các forum . có mục chọn màu sắc cho text . khi nhấp vào biểu tượng của nó thì cho ra 1 bảng màu và chọn màu . cái đó mình phải dùng js để viết à ?
- làm sao để thiết lập 1 hình ảnh nằm riêng 1 dòng hay chữ sẽ nằm bao quanh hình ảnh đó .
mong các bạn giúp cho ..."
-Mảng màu thì dùng html hoặc js đều đựoc mà. dù dùng gì thì cũng phải dùng js để kết nối lại mà.
- Cái nè phải dùng css. thêm style vào thẻ image; có thể tạo ra node image rồi insertnode; hoặc tạo thẻ image có sẵn style rồi dùng inserthtml để thêm vào

phungdinhvu
10-03-2009, 19:17
cho em hỏi em làm thế nào có thể gửi nội dung trong rich text gửi đến 1 trang php.

[=========> Bổ sung bài viết <=========]

em tạo ra 1 trang soạn thảo giống như hướng dẫn nhưng không biết cách gửi cho trang php. Xin giúp đỡ.

ngoc_viet08
13-03-2009, 11:42
à , cho mình hỏi . làm sao lấy nội dung của editor bằng php để lưu vào mysql nhỉ . nó lấy innerHTML của body editor luôn hả ???

[=========> Bổ sung bài viết <=========]

à thấy rồi , ở trang 4. do mình đọc ko kĩ . thanks bạn sacroyant nhé .

[=========> Bổ sung bài viết <=========]

funcition doSend(){
var content=RTE.getContent();
// kiểm tra dữ liệu nếu muốn :
//..............................

//gán giá trị trong editor vào hidden input :
document.f.data.value=content;

//và submit form :
document.f.submit();
}
//
lại có vấn đề nữa . khi submit form = câu lệnh js thế này thì làm sao xác định value của submit .
vì ở trang send.php
em kiểm tra if (S_POST["name"]=="value") vì trang send.php này , em dùng để xử lý nhiều form từ nhiều page khác !

[=========> Bổ sung bài viết <=========]

/////////////
cách nào để chèn 1 mẩu tin query từ csdl vào nội dung body của editor nhỉ .
em sử dụng editor để edit nội dung cũ từ csdl . nhưng ko biết cách nào để viết vào editor , trong khi viết vào form thì dễ . ai biết chỉ giúp .

trinhdiep
16-03-2009, 23:13
Editor này chỉ chạy ở client vì thế mà bạn có thể sử dụng javascript de lấy nội dung từ web server. hoặc binding sẵn lên trang(ví dụ trong tag hidden hoặc trong thẻ div v.v.) rồi nạp vào editor này khi load xong

rootkit
21-03-2009, 12:02
trước giờ tui ko nghĩ ra làm thế nào ma nhưng RTE hiển thị dc mã HTMl trong TextArea giờ thì mới biết ,thanks bạn nhiều lắm vì đã giải quyết đươc khuất mắc của tôi

ngoc_viet08
25-03-2009, 22:46
Editor này chỉ chạy ở client vì thế mà bạn có thể sử dụng javascript de lấy nội dung từ web server. hoặc binding sẵn lên trang(ví dụ trong tag hidden hoặc trong thẻ div v.v.) rồi nạp vào editor này khi load xong
++++++++++++++++++++++++++++++
hình như ko làm được . nếu nạp text ko thì ko nói làm gì . quan trọng là nạp code html . mà theo tớ biết thì mún nạp code html vào editor RTE thì phải dùng mấy code execcommand . tuy nhiên code nạp html vào trực tiếp thì chỉ có trình duyệt FF là có , còn IE thì ko . mệt ở chỗ đó !
insertHTML
Inserts an HTML string at the insertion point (deletes selection). Requires a valid HTML string to be passed in as a value argument. (Not supported by Internet Explorer.)

bên IE chỉ nạp từng món input ,tag vào thui à .
ai biết cách nào để load nội dung chứa html từ csdl vào RTE ko ?

trinhdiep
28-03-2009, 15:07
minh khong biet la ban chi chen doan code html vao vi tri nao do trong editor hay la đoạn code html đó là toàn bộ nôi dung editor.
ban van co the chen code html giong mot doan text. sau khi chen no van hien html nhu thuong.
ban thu lai di; chi can chuoi cua cau chua ma html thoi, con chen text hay html deu duoc ma.
Ngoai ra ban van co the dua code html cua ban vao mot text node roi chen vao giong nhu chen dom. cai ne chac chan ie ho tro
Minh da nghi la ban chen toan bo noi dung editor

[=========> Bổ sung bài viết <=========]

a, ma. con cach thu cong la lay html cua editor; dem ghep code html cua ban vao roi lai gan tro lai editor sau khi gep chuoi.
hihi, cach ne thi trinh duyệt nào chẳng hỗ trợ. có điều là cách này sẽ bị mất vị trí hiện tại dang editor. hic hic

ngoc_viet08
28-03-2009, 16:52
ờ , mình dùng js đã làm được . mình muốn load text từ csdl rồi chèn lại vào RTE . nhưng chỉ hoạt động ở ie , ko hoạt động tại FF . few . vấn đề trình duyệt thật dễ điên .

[=========> Bổ sung bài viết <=========]

à , cái này em làm xong rồi . RTE đã hoàn thiện và đầy đủ . chân thành cám ơn bác chủ topic và các bạn đã tham gia bàn luận giúp em thêm kiến thức . lỗi do em yếu kiến thức nên phát sinh lỗi thôi .
vấn đề trình duyệt là do cơ bản ko vững nên code bị sai !

lilyfor
03-04-2009, 22:08
Cám ơn bạn!.Mình mong có nhiều topic này hơn nữa vì mình đang cần!.

xinbat007
21-06-2009, 20:09
sacroyant oi bạn dùng phần mềm nào soạn thảo php mà màu code đẹp vậy, nhìn rất có hứng thú code, bạn cho mình biết được không? Mà vẫn giữ nguyên được cấu trúc và màu khi post lên diễn đàn nữa chứ

sacroyant
22-06-2009, 13:15
Quên không để ý câu hỏi của bạn này :emlaugh:


Còn một điều khá thú vị nữa mà chưa thấy bàn tới đó là xác định trạng thái của một đoạn text để thay đổi trạng thái nút nhấn tương ứng. Chẳng hạn như trình soạn thảo của google khi di chuyển con trỏ vào vị trí chuỗi in đậm thì nút bold sẽ lõm xuống, di chuyển ra ngoài thì nó sẽ nổi lên

Muốn làm vậy bạn phải sử dụng 1 thuộc tính có tên là focusNode của đối tượng Selection. Thuộc tính này trả về node sâu nhất theo cấu trúc DOM trên vùng đã chọn. Từ đây bạn khảo sát tên và thuộc tính của node cũng như những node trên cấp để xác định style đang được áp dụng với phần văn bản. Chẳng hạn nếu tag name là b hoặc giá trị font-weigth của thuộc tính style là bold, ta biết văn bản được chọn thể hiện dưới dạng in đậm... Tớ thấy tính năng này không cần thiết lắm nên chưa bỏ công làm. Thay vào đó, tớ mới sửa đổi cách thể hiện các hộp thoại chèn link và image, không dùng prompt nữa, để có được nhiều thiết lập hơn. Bạn có thể test thử trên trang chủ của tớ, nhưng phiên bản host bởi Google Page Creator này thì không hỗ trợ upload hình.


http://img386.imageshack.us/img386/3480/73011524.png


sacroyant oi bạn dùng phần mềm nào soạn thảo php mà màu code đẹp vậy, nhìn rất có hứng thú code, bạn cho mình biết được không? Mà vẫn giữ nguyên được cấu trúc và màu khi post lên diễn đàn nữa chứ

Tớ dùng NotePad++ trên Windows và SciTE trên Linux.

Nhưng nếu bạn hỏi về việc trình bày code trên diễn đàn thì tớ trả lời rằng với các forum VBB, chỉ cần đặt code vào trong cặp thẻ
là được.

Ví dụ :




this.blurItem=function(){
this.clearInfo();
if(this.playing){
if(this.cc==this.pointer.cp){
var item=this.collections[this.cc].items[this.pointer.ip];
item.state=1;
item.Out();
}
this.listStateUpdate();
}
}



Sẽ cho kết quả :



this.blurItem=function(){
this.clearInfo();
if(this.playing){
if(this.cc==this.pointer.cp){
var item=this.collections[this.cc].items[this.pointer.ip];
item.state=1;
item.Out();
}
this.listStateUpdate();
}
}

DJT
28-08-2009, 21:13
Topic Close chưa nhỉ ? Nếu chưa bác sacroyant có thể cho em xin YM của bác được ko?

sacroyant
06-09-2009, 13:02
Topic Close chưa nhỉ ? Nếu chưa bác sacroyant có thể cho em xin YM của bác được ko?

Có chuyện gì thế bác DJT? Nếu cần liên hệ với tôi thì bác cứ gửi mail đến địa chỉ sacroyant@gmail.com là được. Mấy năm nay tôi gần như không dùng YM lol

[=========> Bổ sung bài viết <=========]

Tôi vừa nhận email của bạn kenphan19, nội dung như sau :


Chào bạn ^^ !
Cảm ơn bạn đã có bài viết rất hay trên ddth.com. Mình đang viết riêng cho mình 1 cái RTE ^^. Nhưng đến phần focusNodes để nhận biết focus hiện tại đang ở đâu và liệt kê đầy đủ tag con và cha ^^ mình dùng jquery fw để viết ... dựa trên bài hướng dẫn của bạn ! Nếu bạn rãnh, giúp mình việc này tẹo ^^, mình đang rất cần cái đó ^^ tìm hiểu về nó trong jquery thì nó tay :D bạn giúp mình nhé ^^

Cảm ơn trước ^^

Trước đây có 1 bạn thắc mắc vấn đề tương tự trong topic này, và tôi cũng đã trả lời qua loa. Nay xin nói rõ hơn một chút về phương pháp giải quyết.

Từ editor mẫu thứ 2 (http://sacroyantlabs.googlepages.com/rte2.htm), tôi sửa lại chút ít, chỉ giữ 3 nút cơ bản để minh họa.

Việc cần làm đầu tiên là chúng ta thêm vào 2 class CSS để biểu thị trạng thái khác nhau của nút điều khiển định dạng.


.btn {border:outset 1px #fccccc;}
.btn_ {border:inset 1px #fccccc;}

Sau đó trong HTML, chúng ta thiết lập trạng thái mặc định cho các button bằng cách thêm thuộc tính class :


<img class="btn" id="btnBold" src="bold.gif" title="Bold">
<img class="btn" id="btnItalic" src="italic.gif" title="Italic">
<img class="btn" id="btnUnderline" src="underline.gif" title="Underline">

Muốn ghi nhận trạng thái của vùng text đang active, chúng ta phải dựa trên các sự kiện của chuột và bàn phím như click, select, mouseup, keypress... Chẳng hạn người dùng muốn đặt con trỏ vào giữa một từ in đậm, họ có thể điều khiển trên bàn phím, hoặc dùng chuột. Chúng ta cần theo dõi các sự kiện như thế để xác định phần tử đang chọn trong văn bản.

Trong ví dụ mẫu này tôi chỉ theo dõi các sự kiện keypress và mouseup. Script sau được thêm vào khi đã khởi tạo thành công trường soạn thảo. (Hãy nhớ lại đoạn mã khởi tạo đối tượng RichTextEditor hoặc tham khảo code trong file đính kèm bên dưới).



...
this.editor=this.UI.document;
with(this.editor){
designMode='On';
open(); write('<html><head></head><body>'+this.content+'</body></html>');
close();
}
if(this.editor.addEventListener){
this.editor.addEventListener('keypress', checkSelection, true);
this.editor.addEventListener('mouseup', checkSelection, true);
}
else if (this.editor.attachEvent){
this.editor.attachEvent('onkeypress', checkSelection);
this.editor.attachEvent('onmouseup', checkSelection);
}
...


Ở đây có hàm checkSelection, nó có dạng :


function checkSelection(){
var focusNode;
if(window.getSelection){
focusNode=RTE.UI.window.getSelection().focusNode;
}
else if (document.getSelection){
focusNode=RTE.UI.document.getSelection().focusNode ;
}
else if (document.selection){
focusNode=RTE.UI.document.selection.createRange(). parentElement();
}
var currentTag=focusNode.parentNode.tagName;

rel('btnBold').className=(currentTag=='B')?'btn_': 'btn';
rel('btnItalic').className=(currentTag=='I')?'btn_ ':'btn';
rel('btnUnderline').className=(currentTag=='U')?'b tn_':'btn';

if(currentTag=='SPAN'||currentTag=='DIV'){
var atts=focusNode.parentNode.getAttribute('style');
rel('btnBold').className=(atts.indexOf('font-weight: bold;')!==-1)?'btn_':'btn';
rel('btnItalic').className=(atts.indexOf('font-style: italic;')!==-1)?'btn_':'btn';
rel('btnUnderline').className=(atts.indexOf('text-decoration: underline;')!==-1)?'btn_':'btn';
}
}

Không có gì khó hiểu với hàm này. Được gọi khi có sự kiện keypress hoặc mouseup xảy ra trong vùng soạn thảo, checkSelection xác định node đang focus tùy theo trình duyệt. Sau đó nó tìm ra tên thẻ, nếu là B, I hoặc U thì cứ việc thay đổi trạng thái nút định dạng tương ứng.

Nếu là một thẻ "chứa" (containner tag) thì đi tìm giá trị thuộc tính style và xử lý chuỗi này, sau đó mới thay đổi trạng thái nút điều khiển. Ví dụ mẫu được viết cho SPAN và DIV, các thẻ "chứa" khác như blockquote, table... tùy ý bạn thêm vào.

Kết quả thu được các bạn có thể test trên trang minh họa :

http://sacroyantlabs.googlepages.com/rte4.htm

Còn đây là code mẫu : http://sacroyantlabs.googlepages.com/Editor_FocusNode.rar

Trên trang minh họa, các bạn có thể thấy chức năng trên hoạt động chưa hoàn hảo vì muốn chính xác thì phải viết khá nhiều mã lệnh, nhưng phương pháp chung nhìn một cách đơn giản chỉ có như vậy, hy vọng các bạn nắm bắt được và tùy biến cho tốt hơn.

kenphan19
08-09-2009, 02:32
@sacroyant bác giúp viết lun phần focusNode cho button đi :) đang cần cái đó

sacroyant
08-09-2009, 03:59
@sacroyant bác giúp viết lun phần focusNode cho button đi :) đang cần cái đó

Mình vừa gợi ý khá rõ rồi đó :

http://www.ddth.com/showthread.php?p=1814647#post1814647

Phần này mà code chi tiết thì dài lắm, đang lúc mình ít thời gian. Hơn nữa mình thấy cái này có gì hay ho cần thiết đâu chứ :emlaugh:

kenphan19
08-09-2009, 11:04
thanks sacroyant :D đã thấy oỳ ... bài này chưa đọc ...

@sacroyant: tớ dùng command formatblock .. giờ tớ muốn cho class vào thẻ <pre> và thêm thuộc tính thì sao nhỉ

sacroyant
13-09-2009, 16:57
thanks sacroyant :D đã thấy oỳ ... bài này chưa đọc ...

@sacroyant: tớ dùng command formatblock .. giờ tớ muốn cho class vào thẻ <pre> và thêm thuộc tính thì sao nhỉ

Mời bác xem lại kỹ phần này (http://www.ddth.com/showpost.php?p=981685&postcount=36), khi nói về cách xử lý các lệnh Copy, Cut và Paste, tôi đã chỉ rõ làm như thế nào để chèn một chuỗi HTML vào vị trí xác định trong editor. Chỉ cần hiệu chỉnh đôi chút là có những lệnh tương tự lệnh Pre trên trang của tôi :


http://h.imagehost.org/0105/1_42.png

ngoc_viet08
14-09-2009, 21:04
bác sacroyant chắc nghiên cứu về mấy bộ RTE nhiều . ko biết bác có thể public source 1 bộ rte hoàn chỉnh và tiện dụng để đưa vào các project sau này của mọi người ko nhỉ :D

sacroyant
25-09-2009, 10:56
bác sacroyant chắc nghiên cứu về mấy bộ RTE nhiều . ko biết bác có thể public source 1 bộ rte hoàn chỉnh và tiện dụng để đưa vào các project sau này của mọi người ko nhỉ :D

Tôi bỏ nghề lập trình web rồi bác ạ lol

meohoang11
03-10-2009, 18:36
Truoc het minh thanks ban vi da share bo soan thao cho moi nguoi dung va phat trien them.

Hien nay minh dang ung dung cai nay cua ban cho web minh. Tuy nhien, khi minh soan thao 1 phan van ban ( HTML co chua hinh va cac tag ), luu vao database , hien thi ra trang chu thi ok.
Tuy nhien khi minh load lai vao bo soan thao de chinh sua tu database thi no bi loi, khong hien thi luon, ban co the chi minh cach khac phuc khong .

code chen chua minh nhu sau :
<!--
<tr>
<td class="borders" >Miêu tả sản phẩm<td class="borders">
<input type="hidden" name="descrip_long" value="" />
<span id="text_pro_1"><br><br><br><br>&nbsp; Loading...</span>
<script type="text/javascript">
RTE1=new Editor('RTE1','text_pro_1','<?php echo $row['descrip_long'];?>',600, 400);
RTE1.iconPath ='../js/sn/pics/';
RTE1.display();
</script>
<script type="text/javascript" src="clientscript/avim.js"></script>
</td>
</tr>
<tr>
<td class="borders" >Thông số kĩ thuật<td class="borders">
<input type="hidden" name="technical" value="" />
<span id="text_pro_2"><br><br><br><br>&nbsp; Loading...</span>
<script type="text/javascript">
RTE2=new Editor('RTE2','text_pro_2','<?php echo $row['technical'];?>',600, 400);
RTE2.iconPath ='../js/sn/pics/';
RTE2.display();
</script>
<script type="text/javascript" src="clientscript/avim.js"></script>
</td>
</tr>

-->

Code goi ham nhu sau:

<!-- nam chung trong file editor.js
function doSend(form,tag,num,tag2){
var type=num;
if (type==1) {
var content1=RTE1.getContent();
document.forms(form).all(tag).value=content1;
document.forms(form).submit();
}
if (type==2) {
var content2=RTE2.getContent();
document.forms(form).all(tag).value=content2;
document.forms(form).submit();
}
// Khi 2 editor cung nam chung 1 form
if (type==3) {


var content1=RTE1.getContent();
var content2=RTE2.getContent();

document.forms(form).all(tag).value=content1;
document.forms(form).all(tag2).value=content2;


document.forms(form).submit();


}

-->

neu du lieu lay ra tu database dang html don gian thi ok, nhung neu dai va co cac the dac biet nhu image la bi loi lien.

<!-- Đoạn trên mình copy từ mail ra, nên không có dấu, admin thông cảm -->

ke0bong_190589
19-10-2009, 09:41
hic giúp e với e cần một vài tư vấn cụ thể được hem ạ...E đang cần lập 1 gian hàng để làm bán hàng trực tuyến.. nhiều dự định làm để thiết lập nhưng cụ thể về cách tạo lập chưa được rõ lắm e cần có lời khuyên chân thành kinh nghiệm của các a chị giúp e nha nếu được mong a chị sẽ gửi cho e chi tiết nha ví dụ đăng tại trang nào hợp lí cách tạo...làm thế nào sp mình dễ được người tiêu dùng biết đến tất tật><:(( e mau kinh doanh lắm ạ..hic theo nick hoặc email của e được không ạ..thank nhiều lắm ạ.kunyeu.love89@gmail.com e đang cần lắm ạ

vmhuong
29-10-2009, 23:40
Nhờ cao thủ chỉ giúp, tui muốn insert đoạn dữ liệu vào sqlserver sử dụng ado.net, tui không sử dụng rte nào cả, nhưng khi insert mã html vào thì báo lỗi. Ví dụ nếu chèn chữ <br \> vào textbox thì insert lập tức gặp lỗi. Ai giúp tui cái

BoTayConGaQuay
30-10-2009, 00:08
Nhờ cao thủ chỉ giúp, tui muốn insert đoạn dữ liệu vào sqlserver sử dụng ado.net, tui không sử dụng rte nào cả, nhưng khi insert mã html vào thì báo lỗi. Ví dụ nếu chèn chữ <br \> vào textbox thì insert lập tức gặp lỗi. Ai giúp tui cái

Lỗi như thế nào bác không post lên đây luôn?

Tuy nhiên cũng có thể bác bị lỗi validaterequest đó :D, kéo lên đầu trang có dòng <%@ Page validateRequest="true", sửa nó thành <%@ Page validateRequest="false" coi sao?

ngoc_viet08
31-10-2009, 21:40
có thể là vấn đề về các dấu ' " \ / gì đó .
tìm hiểu hàm sql_quote luôn . vừa chống lỗi đó , vừa chống sql injection :D
http://ddth.vn/showthread.php?t=170155

baothoaind
24-02-2010, 16:27
Lỗi: Khi đưa mẩu tin từ csdl đặt vào RTE thì nếu mẩu tin đó có thẻ <p> sẽ không hiển thị RTE được. Đã sử dụng hàm str_replace("<p>","",$mautin);
và str_replace("</p>","<br />",$mautin); nhưng cũng không được. Nhờ sacroyant và các bác tái xuất giúp cho.

hoangthien89
18-04-2010, 17:55
minh dang khong bit lam the nao de co mot editor nhung trong web ma lai co nhung hinh vui dong de them vao cho sinh dong nhi? giong nhu yahoo vay?

phungdinhvu
28-07-2010, 18:09
bác sacroyant ơi cho em hỏi với, em đang làm trang nè http://kstn.tk/kstn.tk/others/newpost.php?location=boxnews, dùng RTE rất đơn giản thui, khi test với FF thi okay, còn khi test với IE thì:
em chọn text rồi, khi click vào font-weight để chọn bold hay italic...thì chỗ selection trong RTE nó bị biến mất, thành ra mấy chức năng này nó bị vô hiệu. Bác có thể chỉ cho em chỗ sai được không? Em tìm hiểu mãi mà không ra.
Thanks các bác nhé.

[=========> Bổ sung bài viết <=========]

bác sacroyant ơi cho em hỏi với, em đang làm trang nè http://kstn.tk/kstn.tk/others/newpost.php?location=boxnews, dùng RTE rất đơn giản thui, khi test với FF thi okay, còn khi test với IE thì:
em chọn text rồi, khi click vào font-weight để chọn bold hay italic...thì chỗ selection trong RTE nó bị biến mất, thành ra mấy chức năng này nó bị vô hiệu. Bác có thể chỉ cho em chỗ sai được không? Em tìm hiểu mãi mà không ra.
Thanks các bác nhé.

[=========> Bổ sung bài viết <=========]

cac bac vao link nay : http://kstn.tk/index.php?showthread=detail.8
test ho em voi, loi la nhu the nay, khi em chon text nhu thia ne:
http://cA5.upanh.com/10.781.14920427.FBY0/testingRTE.png
roi sau do click vao mot vung nao do "font-weight", thi vung chon text no bi mat di, thang thu em khong chon bold hay italic duoc.
Pa con giup em voi, em tim mai khong ra loi ne.
phan tich ca code editor.js cua bac sacroyant ma khong tim duoc. Hix, chi tim duoc cai focus() lam viec voi IE, nhung cung khong duoc. hu hu, giup em voi cac bac oi.

[=========> Bổ sung bài viết <=========]

cac bac vao link nay : http://kstn.tk/index.php?showthread=detail.8
test ho em voi, loi la nhu the nay, khi em chon text nhu thia ne:
http://cA5.upanh.com/10.781.14920427.FBY0/testingRTE.png
roi sau do click vao mot vung nao do "font-weight", thi vung chon text no bi mat di, thang thu em khong chon bold hay italic duoc.
Pa con giup em voi, em tim mai khong ra loi ne.
phan tich ca code editor.js cua bac sacroyant ma khong tim duoc. Hix, chi tim duoc cai focus() lam viec voi IE, nhung cung khong duoc. hu hu, giup em voi cac bac oi.

stalinz
09-08-2010, 15:31
Chào các bạn mình đang nghiên cứu về thằng Rich text edior này. Và mình gặp phải khó khăn này mong sự giúp đỡ của các bạn.
Bây h sau khi định dạng cho văn bản của mình rồi(B,I,U....) mình muốn có một Button và một RichTextEditor mới. Khi click vào button đoạn văn bản đã được định dạng ở trên nó sẽ hiện đúng như thế trên RichTextEditor mới đó(chỉ vần B,U,I thôi). Vậy phải làm thế nào bây h. Mình làm mãi vẫn chưa đựoc mong được sự giúp đỡ.

phungdinhvu
17-08-2010, 14:06
bạn học jquery đi, làm cái nè dễ ý mà,
có gì add nick mình nhé:
phungdinhvu_bka
mình sẽ hướng dẫn cho bạn. Rất vui khi làm quen.

sacroyant
02-09-2010, 13:31
Chào các bạn mình đang nghiên cứu về thằng Rich text edior này. Và mình gặp phải khó khăn này mong sự giúp đỡ của các bạn.
Bây h sau khi định dạng cho văn bản của mình rồi(B,I,U....) mình muốn có một Button và một RichTextEditor mới. Khi click vào button đoạn văn bản đã được định dạng ở trên nó sẽ hiện đúng như thế trên RichTextEditor mới đó(chỉ vần B,U,I thôi). Vậy phải làm thế nào bây h. Mình làm mãi vẫn chưa đựoc mong được sự giúp đỡ.

Sao bạn không đọc trang 1 của thread này nhỉ :emlaugh:

cutuan94nd
03-11-2010, 22:06
bài viết rất hay thanks!

[=========> Bổ sung bài viết <=========]

tôi muốn lập 1 trang web riêng thì làm thế nào ai bít thì nói cho tui bít với

[=========> Bổ sung bài viết <=========]

mình muốn tách lời và nhạc nhưng tách mãi nó vẫn còn cả lời và nhạc ai bít nói cho mình đc ko. mình chỉ muốn nghe nguyên nhạc chứ ko có lời. mong mọi người giúp

phamhaucn
25-12-2010, 23:44
Mấy bác xây dựng rich text editor làm gì trong khi có cái FCKeditor rồi (cực xịn luôn)

ngoc_viet08
26-12-2010, 21:52
nhảm , thế IE có từ trong window cách đây cả chục năm rồi mà FF , chrome mới ra sau này thôi.

vnmaximum
30-12-2010, 23:00
Mình muốn trao đổi link với tất cả các site có nội dung lành mạnh (Không phân biệt thứ hạng, site mới lập hay cũ), chỉ cần có nội dung lành mạnh là được.
Link: sẽ đặt tại http://vnmax.info/
Nếu các bạn đồng ý thì add link sau đó pm cho mình qua yh : cubo_cubi12 hoặc tại đây http://vnmax.info/ mình sẽ add cho các bạn trong thời gian nhanh nhất

Link của mình: <a target="_blank" href="http://vnmax.info/" title="Tin tức nội dung hấp dẫn">tin tức nội dung hấp dẫn</a>

manlivo
30-12-2010, 23:19
Mình ủng hộ, ko nên nghĩ mấy cái FCKeditor xịn rồi mà lại ko dám làm 1 cái khác. Biết đâu bạn sẽ làm được 1 cái còn xịn hơn mấy cái editor ở trên mạng, hoặc ít nhất bạn cũng sẽ có ít kinh nghiệm cho mình.

lucky01hiep
31-12-2010, 07:47
Mình nghĩ các bạn nên sử dụng FCK editor vì nó rất mạnh và tiện nếu ai chưa biết cấu hình hay xài thì liên hệ mình sẽ chỉ dẫn cho ... mấy cái editor khác tuy dung lượng ít mà tính năng không bằng FCK đâu ....

[=========> Bổ sung bài viết <=========]

Ngoài FCK còn có thêm CKEditor kết hợp với thằng CKFinder giao diện cực đẹp nhưng tiếc là thằng CKFinder lại bắt mua bảng quyền.Mình cũng đã cấu hình được cho cả hai rồi .

[=========> Bổ sung bài viết <=========]

Còn muốn gọn nhẹ có thể xài nicEditor cũng tương đối gọn . Chúc các bạn vui

sacroyant
31-12-2010, 11:33
Mấy bác xây dựng rich text editor làm gì trong khi có cái FCKeditor rồi (cực xịn luôn)

Nói như bác thì chúng ta cũng chả nên sinh con đẻ cái làm gì, vì đẻ ra chưa chắc nó đã "xịn" bằng con nhà Gates, con nhà Zuckerberg lol

Trước, trong và sau cái sự đẻ đã có sự "sướng" mà :w00t:

Tớ thì thích dùng cái mình làm ra hơn, muốn nó sao thì nó thế, không thừa không thiếu !


RTE, bản cuối, không hỗ trợ IE7- :

http://sacroyant.uni.cc/Examples/Editor/2010/rte.htm

Bản này định vị các buttons bằng float, nên cho phép co dãn kích thước thoải mái, dùng ảnh sprite all in 1 rất gọn, thêm bảng ký tự đặc biệt (do thỉnh thoảng tớ cần gõ tiếng Pháp), tối thiểu hóa các mục trong hộp thoại chèn ảnh, thêm hộp thoại chèn video từ YouTube...

Cấu trúc chương trình tốt hơn cho phép tạo nhiều hiện thể trên trang. Việc khởi tạo hiện thể ở phía end user được đơn giản hóa đến mức thấp nhất, muốn bất kỳ div nào trở thành vùng soạn thảo, chỉ cần gán cho nó 1 id và gọi :


RTE.apply('divID')

Các thiết lập kích thước cho editor tùy ý chỉ định bên ngoài style sheet của bạn.

Cũng có thể chỉ định kích thước ngay trong khi gán (sẽ ghi đè lên giá trị trong style sheet) :


RTE.apply(elementID, defaultContent, width, height)

Source code shared tại đây, bác nào rảnh rỗi thì xem thử cho vui lol

http://www.box.net/shared/jzd0tbngv1

lucky01hiep
03-01-2011, 14:17
Sinh sao ma hay hơn cái đang có thì sinh chứ cứ yếu hơn thì mất thời gian làm chi ...làm việc khác hay hơn nhé bạn

thuytinhblue
17-01-2011, 09:06
Pác lucky01hiep chỉ giùm mình cách cấu hình upload images trong CKEditor nghe, mình cấu hình hoài mà chưa được, nick mình là thuytinhblue_019 , thank bạn nhiu

violetsunset418
19-01-2011, 13:59
Bài viết rất hữu ít, mình đang tìm hiểu về phần này. Cảm ơn bạn!

[=========> Bổ sung bài viết <=========]

Bạn ơi, bạn có thể viết một bài hướng dẫn cụ thể cách chèn một Rich Text Editor vào website được không?
Cảm ơn bạn trước luôn.
-------
SV sư phạm

cutuan94nd
11-02-2011, 20:21
cho em hỏi là lập trình web dùng cái gì để làm

[=========> Bổ sung bài viết <=========]

ai có thể hướng dẫn mình lập blog được ko nick of mình là tinhyeurerach_nd.

Mr.vanbach
21-02-2011, 17:09
Thật là tuyệt đó mà, tui cần cái này lắm, cảm ơn nha bạn.

Phata
23-02-2011, 10:34
bài viết rất tuyệt, nên làm 1 bản tiếng anh nữa :)

phuocdaivl08
27-04-2011, 14:36
Làm ơn chỉ dùm mình cách lấy nội dung của nó để lưu vào CSDL đi

phamduyvt
12-08-2011, 09:18
chổ insert picture nên thêm chức năng upload hình, có thể nhập link trực tiếp hoặc up 1 cái hình lên rồi lấy link đó chèn vào.

linkinpark13
09-10-2011, 12:00
chào các bạn
minh đang tập làm cái editor nhưng gặp 1 vấn đề chưa giải quyết được là: mình khai báo 1 lớp editor như hướng dẫn nhưng khi chạy file html thì nó chỉ hiện cái khung editor còn cái toolbar thi nó ko hiện . mong các bạn giúp mình .thanks
day la code của mình

webgiavang
14-10-2011, 15:41
Thông tin hữu ích đó bác.

jnomanh
15-10-2011, 15:42
thanks bác nhiều, mình đang cần

traitimmuathu07
31-05-2012, 09:30
làm sao để lấy nội dung của editor lưu lại thành 1 file trong CSDL! ai có thể chỉ giúp mình không. huhu

thodencnt
11-06-2013, 21:18
bài hay, ai cũng cảm ơn, thank mà chỉ thấy đúng 1 người nhấn nút cảm ơn

hta1812
21-06-2013, 12:33
Bài viết khá hay & hữu ích, thanks.