2010-06-09 25 views
14

Có rất nhiều trình soạn thảo WYSIWYG có sẵn trên internet, nhưng tôi chưa tìm thấy một trình soạn thảo thực hiện một số dạng triển khai kéo-thả-thả. Thật dễ dàng để tạo trình soạn thảo của riêng mình, nhưng tôi muốn người dùng có thể kéo các phần tử (ví dụ: mã thông báo) từ bên ngoài vùng có thể chỉnh sửa và thả chúng ở vị trí mà họ chọn bên trong khu vực có thể chỉnh sửa . Nó rất dễ dàng để tiêm html tại một vị trí cụ thể của một yếu tố có thể chỉnh sửa, nhưng làm thế nào để xác định nơi caret nên được khi người dùng đang kéo một DIV trên một số yếu tố trong khu vực có thể chỉnh sửa. Để minh họa rõ hơn những gì tôi đang cố gắng giải thích, hãy xem kịch bản sau đây.Kéo-n-Thả trên nội dungCác yếu tố có thể chỉnh sửa

Diện tích có thể chỉnh sửa (hoặc IFRAME trong chế độ chỉnh sửa hoặc một DIV với thuộc tính contentEditable của nó thiết lập là true) đã có chứa các văn bản sau đây:

"thân mến, xin vui lòng lưu ý ...."

Giờ đây, người dùng sẽ kéo một phần tử biểu thị một số mã thông báo từ danh sách các phần tử, qua vùng có thể chỉnh sửa, di chuyển con trỏ qua văn bản cho đến khi dấu mũ xuất hiện ngay trước dấu phẩy (,) trong văn bản như được hiển thị ở trên. Khi người dùng nhả nút chuột tại vị trí đó, HTML sẽ được tiêm vào đó có thể dẫn đến kết quả như sau:

"Kính gửi {UserFirstName}, xin lưu ý ...".

Tôi không biết liệu có ai đã từng làm bất cứ điều gì tương tự như thế này hay ít nhất biết cách người ta sẽ làm điều này bằng cách sử dụng JavaScript.

Mọi trợ giúp sẽ được đánh giá cao.

Trả lời

6

Đây là cách tiếp cận của tôi để giải quyết vấn đề này các phần tử kéo tùy chỉnh trên các phần tử có thể chỉnh sửa. Vấn đề lớn là người ta không thể xác định độ lệch văn bản của con trỏ chuột khi di chuột qua phần tử có thể chỉnh sửa. Tôi đã thử giả mạo một cú click chuột để thiết lập dấu mũ ở vị trí mong muốn nhưng điều đó không hoạt động. Ngay cả khi nó đã làm, người ta sẽ không nhìn thấy vị trí của các dấu mũ trong khi kéo, nhưng chỉ có kết quả thả.

Vì người ta có thể liên kết các sự kiện di chuột với các phần tử chứ không phải nút văn bản, người ta có thể đặt phần tử có thể chỉnh sửa thành tạm thời không thể chỉnh sửa. Tìm tất cả các phần tử và bọc từng nút văn bản trong một khoảng để không làm gián đoạn luồng văn bản. Mỗi khoảng thời gian sẽ được cấp một tên lớp để chúng tôi có thể tìm lại chúng.

Sau khi gói, một lần nữa nên tìm tất cả các nút văn bản được bao bọc và bọc từng ký tự với một khoảng khác với tên lớp mà bạn có thể tìm lại chúng.

Sử dụng sự kiện ủy quyền người ta có thể thêm sự kiện vào yếu tố có thể chỉnh sửa chính sẽ áp dụng kiểu cho mỗi khoảng ký tự sẽ hiển thị dấu mũ, hình ảnh GIF nhấp nháy làm nền.

Một lần nữa, bằng cách sử dụng ủy quyền sự kiện, bạn nên thêm sự kiện cho sự kiện chuột lên (sự kiện thả) trên mỗi ký tự. Bây giờ người ta có thể xác định độ lệch bằng cách sử dụng vị trí của nhân vật (bù đắp) bên trong vị trí gốc của nó (gói văn bản-nút). Bây giờ người ta có thể hoàn tác tất cả các gói, giữ một tham chiếu đến tính toán bù đắp và trong khi hoàn tác các gói giữ một tham chiếu đến nút văn bản áp dụng.

Sử dụng phạm vi & đối tượng lựa chọn của trình duyệt, bây giờ người ta có thể đặt lựa chọn bằng cách sử dụng tính toán bù trừ cho nút văn bản có thể áp dụng và tiêm HTML được yêu cầu ở vị trí mới được chọn (vị trí dấu mũ), et viola!

Ở đây sau một đoạn sử dụng jQuery sẽ tìm textnodes, bọc chúng:

editElement.find("*:not(.text-node)").contents().filter(function(){ 
    return this.nodeType != 1; 
}).wrap("<span class=\"text-node\"/>"); 

Để tìm mỗi text-nút và quấn mỗi nhân vật, sử dụng:

editElement.find(".text-node").each(function() 
{ 
    var textnode = $(this), text = textnode.text(), result = []; 

    for (var i = 0; i < text.length; i++) result.push(text.substr(i, 1)); 

    textnode.html("<span class=\"char\">" 
     + result.join("</span><span class=\"char\">") + "</span>"); 
}); 

Để hoàn tác các gói:

editElement.find(".text-node").each(function() 
{ 
    this.parentNode.replaceChild(document.createTextNode($(this).text()), this); 
}); 

Hy vọng cách tiếp cận này sẽ giúp những người gặp khó khăn tương tự

+1

Có thể không bắt buộc phải áp dụng sự kiện mouseup được ủy quyền trên các ký tự kéo dài như đã đề cập ở trên, có thể sử dụng thuộc tính sự kiện ban đầu của sự kiện có thể hủy để xác định xem thực tế có thể kéo thả được trên một khoảng ký tự hay không. Chỉ cần FYI .... – Raybiez

1

Hiện tại API HTML5 đang được phát triển để thực hiện việc này, nhưng tiếc là IE không hỗ trợ nó. Chỉnh sửa: Rõ ràng IE thực sự hỗ trợ kéo và thả, nhưng tôi không quen thuộc với cách hoạt động của nó. Hãy thử Googling "Kéo và thả IE".

Hãy thử nhìn vào các trang web này:

+0

Một đồng nghiệp của tôi đã tìm thấy giải pháp, đó là câu hỏi mà tôi đã đặt câu hỏi. Tôi sẽ đăng giải pháp ở đây sớm – Raybiez

+0

Than ôi, giải pháp của anh ấy không thực sự áp dụng được. Cuộc săn lùng đang trở lại ... grrr – Raybiez

+0

@Raybiez Có lẽ bạn có thể chỉnh sửa câu hỏi của mình để thêm giải pháp không hoạt động? Điều đó cũng sẽ có tác dụng phụ của việc đẩy câu hỏi này trở lại trang đầu. – Na7coldwater

2

Nếu tôi hiểu những gì bạn đang nói, thì đây chỉ là kéo và thả cơ bản. Giải pháp dưới đây nên gần với câu trả lời tốt nhất cho FIREFOX. Tôi chắc rằng có các chức năng khác nhau cho IE. Truy cập http://www.html5rocks.com/en/tutorials/dnd/basics/ để được trợ giúp thêm.

Đặt thuộc tính "có thể kéo" của đối tượng bạn muốn kéo và đặt phương thức "ondragstart" của đối tượng thành "dragStartHandler" hoặc bất kỳ chức năng nào của bạn được gọi.

// You can set this to 'text/plain' if you don't want to insert HTML content 
var internalDNDType = 'text/html'; 

function dragStartHandler(event) { 
    // This is whatever html data you want to insert. 
    var textContent = "<b>"+userFirstName+"</b>"; 

    event.dataTransfer.setData(internalDNDType, textContent); 
    event.dataTransfer.effectAllowed = 'copy'; 
} 

function dragEnterHandler(event) 
{ 
    event.preventDefault(); 
    return false; 
} 

function dragOverHandler(event) 
{ 
    event.preventDefault(); 
    return false; 
} 

function dropHandler(event) { 
    event.preventDefault(); 
    event.stopPropogation(); 
    return false; 
} 
+0

Cảm ơn bạn đã phản hồi, tuy nhiên điều này dựa trên HTML5 và ứng dụng phải hỗ trợ các trình duyệt cũ. Đối với ứng dụng mới cập nhật không hỗ trợ trình duyệt cũ, phương pháp này sẽ phù hợp nhất. – Raybiez

Các vấn đề liên quan