2012-01-01 37 views
22

Mã như:onChange kiện với contenteditable

...text <span contenteditable="true" onChange="someFunction()">blah blah</span> text... 

Sự kiện onChange không hoạt động. (ít nhất là trong FireFox)
Tôi không muốn sử dụng các thẻ văn bản/đầu vào, bởi vì phải có sẵn để chỉ thay đổi các từ cụ thể trong văn bản và phải được hiển thị nội dòng (không chặn).

Có cách nào để thực hiện điều đó không?

+1

Tại sao không sử dụng một yếu tố 'input' và phong cách xa biên giới/padding và làm trong 'hiển thị: inline' hoặc 'display: inline-block' – Chad

Trả lời

6

Chức năng tôi đã viết:
Một cuộc gọi của chức năng này sẽ sửa tất cả các phần tử có thể chỉnh sửa nội dung trong trang.

function fix_onChange_editable_elements() 
{ 
    var tags = document.querySelectorAll('[contenteditable=true][onChange]');//(requires FF 3.1+, Safari 3.1+, IE8+) 
    for (var i=tags.length-1; i>=0; i--) if (typeof(tags[i].onblur)!='function') 
    { 
    tags[i].onfocus = function() 
    { 
     this.data_orig=this.innerHTML; 
    }; 
    tags[i].onblur = function() 
    { 
     if (this.innerHTML != this.data_orig) 
     this.onchange(); 
     delete this.data_orig; 
    }; 
    } 
} 
+1

Nếu bạn cần biết về các thay đổi "trực tiếp", nguyên tắc trên có thể được điều chỉnh để hoạt động trong 'setInterval' (với cài đặt khoảng thời gian hợp lý và' clearInterval' cuối cùng). –

23

Không thực sự. Các trình duyệt WebKit gần đây hỗ trợ sự kiện HTML5 input trên các yếu tố contenteditable, lý tưởng nhưng không được hỗ trợ trong các trình duyệt khác (CẬP NHẬT 31 tháng 12 năm 2012: Firefox hỗ trợ phiên bản này là phiên bản 14). Nếu không, bạn có thể nhận được bằng DOM mutation eventsDOMNodeInserted, DOMNodeRemovedDOMCharacterDataModified, nhưng có hai nhược điểm: trước hết, chúng không được hỗ trợ trong IE < 9 hoặc bất kỳ phiên bản nào của Opera cho các yếu tố contenteditable và thứ hai. trong các tác phẩm, có nghĩa là chúng có thể được thay thế trong các trình duyệt trong tương lai.

Sống dụ: http://jsfiddle.net/MBags/

Hoặc bạn có thể đi cấp dưới và xử lý chủ chốt, chuột và các sự kiện vào clipboard (cutpaste), mà sẽ làm việc trong tất cả các trình duyệt chính nhưng sẽ có nghĩa là bạn sẽ cần phải kiểm tra xem nội dung có thể chỉnh sửa đã thay đổi mỗi khi một sự kiện như vậy kích hoạt, điều này sẽ khiến người dùng gặp khó khăn và gây hại cho những nội dung lớn.

+0

onInput event là giải pháp rất kém. lý do đầu tiên - nó xảy ra mỗi khi người dùng thay đổi ngay cả một chữ cái duy nhất. lý do thứ hai - nó không hoạt động ngay cả trong FireFox 8.0 –

+4

@ Dani-Br: Cái gì? Câu trả lời của tôi nói rằng sự kiện 'input' chỉ được hỗ trợ trong WebKit, do đó không có trong Firefox. Thứ hai, câu hỏi của bạn không rõ ràng về * khi * bạn cần phát hiện các thay đổi đối với nội dung có thể chỉnh sửa; sự kiện 'input' là sự kiện tương tự nhất với sự kiện' change' của đầu vào biểu mẫu, mặc dù tôi thừa nhận rằng chúng khá khác nhau. –

+0

Thật không may sự kiện _input_ không hoạt động trên các phần tử _contenteditable_ trong IE, thậm chí không có trong IE10! – AnAurelian

4

Bởi vì các yếu tố không đầu vào không có các sự kiện giống như đầu vào truyền thống, bạn phải tự mình kết hợp thứ gì đó với nhau. Để kết thúc:

var editable = document.querySelectorAll('div[contentEditable]'); 

for (var i=0, len = editable.length; i<len; i++){ 
    editable[i].setAttribute('data-orig',editable[i].innerHTML); 

    editable[i].onblur = function(){ 
     if (this.innerHTML == this.getAttribute('data-orig')) { 
      // no change 
     } 
     else { 
      // change has happened, store new value 
      this.setAttribute('data-orig',this.innerHTML); 
     } 
    }; 
} 

JS Fiddle demo.

Mặc dù được ghi chú bởi Tim Down điều này không cần thiết trong thời gian quá lâu, với ngoại lệ rõ ràng là hỗ trợ các trình duyệt cũ hơn.

9

Tôi đã tạo plugin jQuery để thực hiện việc này.

(function ($) { 
    $.fn.wysiwygEvt = function() { 
     return this.each(function() { 
      var $this = $(this); 
      var htmlOld = $this.html(); 
      $this.bind('blur keyup paste copy cut mouseup', function() { 
       var htmlNew = $this.html(); 
       if (htmlOld !== htmlNew) { 
        $this.trigger('change'); 
        htmlOld = htmlNew; 
       } 
      }) 
     }) 
    } 
})(jQuery); 

Bạn có thể chỉ cần gọi $('.wysiwyg').wysiwygEvt();

Bạn cũng có thể xóa/thêm các sự kiện nếu bạn muốn

+0

Giống như mã của bạn nhưng 'cái đó' có vẻ không xác định. – AnthonyVO

+0

cảm ơn, cố định .. – Blowsie

+1

Tiếp tục, toàn bộ điều này sẽ chỉ làm việc một lần, hoặc tất cả các sự kiện thời gian khi bạn chỉ nhòe vào và ra nếu bạn thực hiện một thay đổi một lần, vì 'htmlold' chỉ được xác định một lần và không bao giờ ghi đè lên trạng thái hiện tại! – Val

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