সন্তোষজনক পরিবর্তন ইভেন্ট


359

আমি একজন ব্যবহারকারী তার সম্পাদনার একটি বিষয়বস্তু একটি ফাংশন চালাতে চান divসঙ্গে contenteditableঅ্যাট্রিবিউট। একটি onchangeইভেন্টের সমতুল্য কি ?

আমি jQuery ব্যবহার করছি তাই jQuery ব্যবহার করে এমন কোনও সমাধান পছন্দ করা যায়। ধন্যবাদ!


আমি সাধারণত এই কাজ: document.getElementById("editor").oninput = function() { ...}
বসজ

উত্তর:


311

আমি শ্রোতাদের সম্পাদনাযোগ্য উপাদান দ্বারা চালিত মূল ইভেন্টগুলিতে সংযুক্ত করার পরামর্শ দেব, যদিও আপনার সচেতন হওয়া প্রয়োজন keydownএবং keypressবিষয়বস্তু নিজেই পরিবর্তিত হওয়ার আগে ইভেন্টগুলি নিক্ষেপ করা হবে। এটি সামগ্রীটি পরিবর্তনের প্রতিটি সম্ভাব্য উপায়কে কভার করবে না: ব্যবহারকারী সম্পাদনা বা প্রসঙ্গ ব্রাউজার মেনু থেকে কাটা, অনুলিপি এবং পেস্টও ব্যবহার করতে পারে, তাই আপনি cut copyএবং pasteইভেন্টগুলিও পরিচালনা করতে চাইতে পারেন । এছাড়াও, ব্যবহারকারী পাঠ্য বা অন্যান্য সামগ্রী ফেলে দিতে পারেন, সুতরাং সেখানে আরও ইভেন্ট রয়েছে ( mouseupউদাহরণস্বরূপ)। আপনি ফ্যালব্যাক হিসাবে উপাদানটির সামগ্রীগুলি পোল করতে চাইতে পারেন want

আপডেট 29 অক্টোবর 2014

HTML5 এর inputঘটনা দীর্ঘ মেয়াদে উত্তর। লেখার সময় এটি contenteditableবর্তমান মোজিলা (ফায়ারফক্স ১৪ থেকে) এবং ওয়েবকিট / ব্লিঙ্ক ব্রাউজারগুলির উপাদানগুলির জন্য সমর্থিত তবে আইই নয়।

ডেমো:

document.getElementById("editor").addEventListener("input", function() {
    console.log("input event fired");
}, false);
<div contenteditable="true" id="editor">Please type something in here</div>

ডেমো: http://jsfiddle.net/ch6yn/2691/


11
আমিও, যোগ করা উচিত এটি ব্রাউজারের সম্পাদনা মেনু বা কাটা প্রসঙ্গ মেনু ব্যবহার করে একটি সম্পাদনাযোগ্য উপাদান পরিবর্তন করতে সম্ভব কপি বা, বিষয়বস্তু পেস্ট যাতে আপনি হ্যান্ডেল করতে হবে cut, copyএবং paste(আইই 5+, ফায়ারফক্স যে তাদের সমর্থন ব্রাউজারে ঘটনা 3.0+, সাফারি 3+, ক্রোম)
টিম ডাউন

4
আপনি কীআপটি ব্যবহার করতে পারেন, এবং আপনার সময় সংক্রান্ত সমস্যা হবে না।
ব্লুসি

2
@ ব্লোজি: হ্যাঁ, তবে ইভেন্টটি আগুনের আগে আপনি অটো-রিপিটেড কীপ্রেস থেকে প্রচুর পরিবর্তনগুলি সম্পন্ন করার সম্ভাবনা শেষ করতে পারেন। সম্পাদনাযোগ্য পাঠ্য পরিবর্তন করার অন্যান্য উপায়ও রয়েছে যা এই উত্তরের দ্বারা বিবেচিত হয় না, যেমন সম্পাদনা এবং প্রসঙ্গ মেনুগুলির মাধ্যমে ড্রাগ এবং ড্রপ এবং সম্পাদনা। দীর্ঘমেয়াদী, এই সমস্তগুলি HTML5 inputইভেন্টের আওতায় আসা উচিত ।
টিম ডাউন

1
আমি ডেবিউ দিয়ে কিআপ করছি।
আয়ন টান

1
@ অ্যান্ড্রয়েডেভ আমি ক্রোম পরীক্ষা করে দেখি এবং ইনপুট ইভেন্টটিও অনুলিপি দ্বারা কপি পেস্ট এবং কাটা কাটাতে হয়: w3c.github.io/uievents/#events-inputevents
ফিশবোন

188

এখানে একটি আরও কার্যকর সংস্করণ যা onসমস্ত কনটেন্টেবলের জন্য ব্যবহার করে । এটি শীর্ষ উত্তরগুলি এখানে ভিত্তি করে।

$('body').on('focus', '[contenteditable]', function() {
    const $this = $(this);
    $this.data('before', $this.html());
}).on('blur keyup paste input', '[contenteditable]', function() {
    const $this = $(this);
    if ($this.data('before') !== $this.html()) {
        $this.data('before', $this.html());
        $this.trigger('change');
    }
});

প্রকল্পটি এখানে: https://github.com/balupton/html5edit


আমার জন্য নিখুঁত কাজ করেছেন, উভয়ই কফিস্ক্রিপ্ট এবং জাভাস্ক্রিপ্টের জন্য ধন্যবাদ
jwilcox09

7
কিছু পরিবর্তন রয়েছে যা সন্তোষজনকভাবে অস্পষ্ট না হওয়া অবধি এই কোডটির দ্বারা ধরা পড়বে না। উদাহরণস্বরূপ: টেনে আনুন এবং ছেড়ে দেওয়া, প্রসঙ্গ মেনু থেকে কাটা এবং ব্রাউজার উইন্ডো থেকে আটকানো। আমি একটি উদাহরণ পৃষ্ঠা সেটআপ করেছি যা এই কোডটি ব্যবহার করে যা আপনি এখানে ইন্টারঅ্যাক্ট করতে পারেন ।
jrullmann

@ জুরুলম্যান হ্যাঁ এই কোডটি নিয়ে ছবিগুলি টেনে আনার সময় আমার সমস্যা ছিল কারণ এটি চিত্রের লোড শোনেনি (এটি আমার ক্ষেত্রে পুনরায় আকার দেওয়ার অপারেশন পরিচালনা করতে সমস্যা ছিল)
সেবাস্তিয়ান লোরবার

@jrullmann অত্যন্ত চমৎকার, এই কাজ তারপর জাভাস্ক্রিপ্ট সঙ্গে মান পরিবর্তন, কনসোলে দেখুন: document.getElementById('editor_input').innerHTML = 'ssss'

1
@ নাডাবিবি এটি করা উচিত নয়, এটি "যদি ($ this.data ('আগে'))! == .h this.html ()) {" এর জন্য রয়েছে
4:42 এ বাল্পটন

52

ব্যবহার করার কথা বিবেচনা MutationObserver । এই পর্যবেক্ষকরা ডিওএম-র পরিবর্তনের বিষয়ে প্রতিক্রিয়া দেখাতে এবং মিউটেশন ইভেন্টগুলিতে পারফরম্যান্স প্রতিস্থাপন হিসাবে ডিজাইন করা হয়েছে

পেশাদাররা:

  • কোনও পরিবর্তন ঘটে গেলে আগুন লাগে , যা অন্যান্য উত্তরের পরামর্শ অনুসারে মূল ইভেন্টগুলি শোনার মাধ্যমে অর্জন করা মুশকিল। উদাহরণস্বরূপ, এই সমস্তগুলি ভালভাবে কাজ করে: প্রসঙ্গ মেনুতে টেনে আনুন এবং ছাড়ুন, ইটালিকাইজিং করুন, অনুলিপি করুন / কাটাবেন / আটকান।
  • কর্মক্ষমতা মাথায় রেখে তৈরি করা হয়েছে।
  • সরল, সোজা কোড। কোডটি বুঝতে ও ডিবাগ করা অনেক সহজ যা 10 টি ইভেন্ট শোনার কোডের চেয়ে একটি ইভেন্ট শোনায়।
  • গুগলের একটি দুর্দান্ত মিউটেশন সারসংক্ষেপ গ্রন্থাগার রয়েছে যা মিউটেশনঅবার্সারগুলি ব্যবহার করা খুব সহজ করে তোলে।

কনস:

  • ফায়ারফক্স (14.0+), ক্রোম (18+), বা আইই (11+) এর একটি অতি সাম্প্রতিক সংস্করণ প্রয়োজন।
  • নতুন এপিআই বুঝতে
  • সেরা অভ্যাস বা কেস স্টাডি সম্পর্কে এখনও প্রচুর তথ্য পাওয়া যায় না

আরও জানুন:


এটি এইচটিএমএল 5 inputইভেন্টের মতো নয় (যা contenteditableমিউশনেশন পর্যবেক্ষকদের সমর্থন করে এমন সমস্ত ওয়েবকিট এবং মজিলা ব্রাউজারগুলিতে সমর্থিত), যেহেতু স্ক্রিপ্টের পাশাপাশি ব্যবহারকারীর ইনপুটটির মাধ্যমে ডিওএম রূপান্তর ঘটতে পারে তবে এটি ব্রাউজারগুলির পক্ষে এটি একটি কার্যকর সমাধান। আমি ধারণা করি এটি inputইভেন্টের চেয়েও পারফরম্যান্সের ক্ষতি করতে পারে তবে এর পক্ষে আমার কাছে কোনও শক্ত প্রমাণ নেই।
টিম ডাউন

2
+1, তবে কী আপনি বুঝতে পেরেছেন যে মিউটেশন ইভেন্টগুলি কনটেন্টেটেবলের জন্য লাইন ফিডের প্রভাবগুলি রিপোর্ট করে না? আপনার স্নিপেটে এন্টার টিপুন।
সিটিকিড

4
@ সিটিকিড: কারণ স্নিপেট কেবলমাত্র চরিত্রের ডেটা পরিবর্তনের জন্য নজর রাখছে। এটি ডিওএম কাঠামোগত পরিবর্তনগুলিও পর্যবেক্ষণ করা সম্ভব। উদাহরণস্বরূপ jsfiddle.net/4n2Gz/1 দেখুন ।
টিম ডাউন

ইন্টারনেট এক্সপ্লোরার 11+ মিউটেশন পর্যবেক্ষকদের সমর্থন করে ।
সাম্পসন

আমি যাচাই করতে সক্ষম হয়েছি (কমপক্ষে ক্রোম 43.0.2357.130 এ) যে inputপ্রতিটি পরিস্থিতিতে এইচটিএমএল 5 ইভেন্টে আগুন লেগেছিল (নির্দিষ্টভাবে প্রসঙ্গ মেনুতে টানুন এবং ছাড়ুন, নকল করুন / কাটা / পেস্ট করুন)। আমি বোল্ডিং ডাব্লু / সেমিডি / সিটিআরএল + বি পরীক্ষা করেও প্রত্যাশিত ফলাফল পেয়েছি। আমিও চেক করা এবং যে যাচাই করতে সক্ষম ছিল inputঘটনা না কর্মসূচিগত পরিবর্তন লক্ষ্য করে গুলি (যা সুস্পষ্ট মনে হলেও তর্কসাপেক্ষে প্রাসঙ্গিক MDN পৃষ্ঠাতে কিছু বিভ্রান্তিকর ভাষা বিপরীত; পৃষ্ঠার এখানে নীচে দেখতে কি আমি কি বলতে চান: ডেভেলপার .mozilla.org / en-মার্কিন / ডকস / ওয়েব / ইভেন্ট / ইনপুট )
মিকর্ম্কনিল

22

আমি লাউয়ানটসিনের উত্তরকে এরকমভাবে সংশোধন করেছি এবং এটি আমার পক্ষে কাজ করে। আমি কীপ্রেসের পরিবর্তে কীপ ইভেন্টটি ব্যবহার করি যা দুর্দান্ত কাজ করে।

$('#editor').on('focus', function() {
  before = $(this).html();
}).on('blur keyup paste', function() { 
  if (before != $(this).html()) { $(this).trigger('change'); }
});

$('#editor').on('change', function() {alert('changed')});

22

অ jQuery দ্রুত এবং নোংরা উত্তর:

function setChangeListener (div, listener) {

    div.addEventListener("blur", listener);
    div.addEventListener("keyup", listener);
    div.addEventListener("paste", listener);
    div.addEventListener("copy", listener);
    div.addEventListener("cut", listener);
    div.addEventListener("delete", listener);
    div.addEventListener("mouseup", listener);

}

var div = document.querySelector("someDiv");

setChangeListener(div, function(event){
    console.log(event);
});

3
এই মোছার ঘটনাটি কী?
জেমস বিড়াল

7

দুটি বিকল্প:

1) আধুনিক (চিরসবুজ) ব্রাউজারগুলির জন্য: "ইনপুট" ইভেন্টটি বিকল্প "পরিবর্তন" ইভেন্ট হিসাবে কাজ করবে।

https://developer.mozilla.org/en-US/docs/Web/Events/input

document.querySelector('div').addEventListener('input', (e) => {
    // Do something with the "change"-like event
});

অথবা

<div oninput="someFunc(event)"></div>

বা (jQuery সহ)

$('div').on('click', function(e) {
    // Do something with the "change"-like event
});

২) আইই ১১ এবং আধুনিক (চিরসবুজ) ব্রাউজারগুলির জন্য অ্যাকাউন্ট করতে: এটি ডিভের মধ্যে উপাদান পরিবর্তন এবং তাদের বিষয়বস্তুর জন্য নজর রাখে।

https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

var div = document.querySelector('div');
var divMO = new window.MutationObserver(function(e) {
    // Do something on change
});
divMO.observe(div, { childList: true, subtree: true, characterData: true });

7

const p = document.querySelector('p')
const result = document.querySelector('div')
const observer = new MutationObserver((mutationRecords) => {
  result.textContent = mutationRecords[0].target.data
  // result.textContent = p.textContent
})
observer.observe(p, {
  characterData: true,
  subtree: true,
})
<p contenteditable>abc</p>
<div />


2
এটি আকর্ষণীয় দেখায়। কেউ কিছু ব্যাখ্যা দিতে পারেন? 😇
ওওআইইইই

3

আমার জন্য যা কাজ করেছে তা এখানে:

   var clicked = {} 
   $("[contenteditable='true']").each(function(){       
        var id = $(this).attr("id");
        $(this).bind('focus', function() {
            // store the original value of element first time it gets focus
            if(!(id in clicked)){
                clicked[id] = $(this).html()
            }
        });
   });

   // then once the user clicks on save
   $("#save").click(function(){
            for(var id in clicked){
                var original = clicked[id];
                var current = $("#"+id).html();
                // check if value changed
                if(original != current) save(id,current);
            }
   });

3

আমি বিষয়টি তদন্ত করার সময় এই থ্রেডটি খুব সহায়ক হয়েছিল।

আমি এখানে উপলভ্য কিছু কোডকে একটি jQuery প্লাগইনে রূপান্তর করেছি যাতে এটি পুনরায় ব্যবহারযোগ্য ফর্মের মধ্যে থাকে, প্রাথমিকভাবে আমার প্রয়োজনগুলি পূরণ করার জন্য তবে অন্যরা সন্তোষজনক ট্যাগ ব্যবহার করে জাম্পস্টার্ট করার জন্য একটি সহজ ইন্টারফেসের প্রশংসা করতে পারে।

https://gist.github.com/3410122

হালনাগাদ:

এর ক্রমবর্ধমান জনপ্রিয়তার কারণে প্লাগইনটি মেকসাইটস.org দ্বারা গৃহীত হয়েছে

এখান থেকে উন্নয়ন অব্যাহত থাকবে:

https://github.com/makesites/jquery-contenteditable


2

সমাধানটি আমি ব্যবহার করে শেষ করেছি এবং কল্পিতভাবে কাজ করি। পরিবর্তে আমি $ (এটি) .text () ব্যবহার করি কারণ আমি কেবলমাত্র একটি লাইন ডিভি ব্যবহার করছি যা সামগ্রী সম্পাদনযোগ্য। তবে আপনি এইচটিএমএল () ব্যবহার করতে পারেন এইভাবে আপনাকে বৈশ্বিক / অ-বৈশ্বিক ভেরিয়েবলের সুযোগ সম্পর্কে চিন্তা করতে হবে না এবং এর আগে আসলে সম্পাদক ডিভের সাথে সংযুক্ত রয়েছে।

$('body').delegate('#editor', 'focus', function(){
    $(this).data('before', $(this).html());
});
$('#client_tasks').delegate('.task_text', 'blur', function(){
    if($(this).data('before') != $(this).html()){
        /* do your stuff here - like ajax save */
        alert('I promise, I have changed!');
    }
});

1

টাইমার এবং "সংরক্ষণ" বোতামগুলি এড়ানোর জন্য, উপাদান ফোকাস হারিয়ে ফেললে আপনি অস্পষ্ট ইভেন্ট উইচ ফায়ার ব্যবহার করতে পারেন। তবে নিশ্চিত হয়ে উঠুন যে উপাদানটি আসলে পরিবর্তিত হয়েছিল (কেবলমাত্র দৃষ্টি নিবদ্ধ করা এবং ডিফল্ট করা হয়নি), এর সামগ্রীটিকে তার শেষ সংস্করণের সাথে তুলনা করা উচিত। অথবা এই উপাদানটিতে কিছু "নোংরা" পতাকা সেট করতে কীডাউন ইভেন্টটি ব্যবহার করুন।


1

জিকিউরির একটি সহজ উত্তর, আমি কেবল এই কোডটি তৈরি করেছি এবং ভেবেছিলাম এটি অন্যদের জন্যও সহায়ক হবে be

    var cont;

    $("div [contenteditable=true]").focus(function() {
        cont=$(this).html();
    });

    $("div [contenteditable=true]").blur(function() {
        if ($(this).html()!=cont) {
           //Here you can write the code to run when the content change
        }           
    });

দ্রষ্টব্য যে $("div [contenteditable=true]")কোনও ডিভের সমস্ত বাচ্চাকে প্রত্যক্ষ বা অপ্রত্যক্ষভাবে নির্বাচন করবে, এটি সন্তোষজনক।
ব্রুনো

1

জিকুরির উত্তর নেই ...

function makeEditable(elem){
    elem.setAttribute('contenteditable', 'true');
    elem.addEventListener('blur', function (evt) {
        elem.removeAttribute('contenteditable');
        elem.removeEventListener('blur', evt.target);
    });
    elem.focus();
}

এটি ব্যবহার করতে, id = "myHeader" সহ একটি শিরোনাম উপাদান কল করুন (বলুন)

makeEditable(document.getElementById('myHeader'))

ফোকাসটি হারা না হওয়া পর্যন্ত এই উপাদানটি এখন ব্যবহারকারী সম্পাদনাযোগ্য হবে।


5
উহ, ডাউনটা কেন কোনও ব্যাখ্যা ছাড়াই? এটি উত্তর লিখেছেন এমন ব্যক্তি এবং উত্তর যারা পরে পড়েছেন তাদের উভয়ের পক্ষে এটি বিদ্রূপ করে।
মাইক উইলিস

0

কন্টেন্টএডিয়েটেবল অ্যাট্রিবিউটের সাথে কোনও উপাদান পরিবর্তিত হলে, প্রস্তাবিত পদ্ধতির সংস্করণটি জ্বলে উঠবে না, একটি প্রস্তাবিত পদ্ধতির সংস্করণটি "সংরক্ষণ" করার জন্য একটি বোতাম যুক্ত করা যেতে পারে ।

এই প্লাগইনটি পরীক্ষা করুন যা সমস্যাটিকে সেইভাবে পরিচালনা করে:


বংশধরগণ, দশ বছর এগিয়ে এবং জন্য কোন প্রয়োজন নেই একটি বাটন "সংরক্ষণ করুন", গৃহীত উত্তর এর jsfiddle পরীক্ষা
revelt

0

মিউটেশনভেন্টস এর অধীনে DOMCharacterDataModified ব্যবহার করা একইটির দিকে নিয়ে যাবে। ভুল মান পাঠানো রোধ করতে টাইমআউট সেটআপ করা হয়েছে (যেমন ক্রোমে আমার স্পেস কী নিয়ে কিছু সমস্যা হয়েছিল)

var timeoutID;
$('[contenteditable]').bind('DOMCharacterDataModified', function() {
    clearTimeout(timeoutID);
    $that = $(this);
    timeoutID = setTimeout(function() {
        $that.trigger('change')
    }, 50)
});
$('[contentEditable]').bind('change', function() {
    console.log($(this).text());
})

JSFIDDLE উদাহরণ


1
+1 - DOMCharacterDataModifiedযখন ব্যবহারকারী বিদ্যমান পাঠ্যটি সংশোধন করে, তখন গুলি চালিত হবে না, উদাহরণস্বরূপ গা bold় বা তির্যক প্রয়োগ করা। DOMSubtreeModifiedএই ক্ষেত্রে আরও উপযুক্ত। এছাড়াও, লোকদের মনে রাখা উচিত যে উত্তরাধিকারী ব্রাউজারগুলি এই ইভেন্টগুলিকে সমর্থন করে না।
অ্যান্ডি ই

3
পারফরমেন্স সমস্যার কারণে মিউটেশন ইভেন্টগুলি ডাব্লু 3 সি দ্বারা অবমূল্যায়ন করা হয়েছে কেবল একটি নোট। এই স্ট্যাক ওভারফ্লো প্রশ্নটিতে আরও পাওয়া যাবে ।
jrullmann

0

এটি করার জন্য আমি একটি jQuery প্লাগইন তৈরি করেছি।

(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')
                }
            })
        })
    }
})(jQuery);

আপনি কেবল কল করতে পারেন $('.wysiwyg').wysiwygEvt();

আপনি চাইলে ইভেন্টগুলি সরিয়ে / যুক্ত করতে পারেন


2
সম্পাদনাযোগ্য সামগ্রী দীর্ঘায়িত হওয়ায় ( innerHTMLব্যয়বহুল) এগুলি ধীর এবং অচল হয়ে যাবে । আমি inputইভেন্টটি যেখানে উপস্থিত রয়েছে তা ব্যবহার করার এবং এটির মতো কিছুতে ফিরে আসার পরামর্শ দিচ্ছি তবে একরকম ধমক দিয়ে।
টিম ডাউন

0

কৌণিক 2+ এ

<div contentEditable (input)="type($event)">
   Value
</div>

@Component({
  ...
})
export class ContentEditableComponent {

 ...

 type(event) {
   console.log(event.data) // <-- The pressed key
   console.log(event.path[0].innerHTML) // <-- The content of the div 
 }
}


0

নিম্নলিখিত সহজ সমাধান অনুসরণ করুন

ইন .ts:

getContent(innerText){
  this.content = innerText;
}

ইন। এইচটিএমএল:

<div (blur)="getContent($event.target.innerHTML)" contenteditable [innerHTML]="content"></div>

-1

এই ধারণাটি দেখুন। http://pastie.org/1096892

আমি মনে করি এটি নিকটে এইচটিএমএল 5 সত্যই পরিবর্তন ইভেন্ট যুক্ত করতে হবে। কেবলমাত্র সমস্যাটি হ'ল কলব্যাক ফাংশনটি যদি মূল্যায়ন করে (যদি আগে == $ (এটি) .html ()) সামগ্রীটি আসলে $ (এটি) .html () এ আপডেট হয়। সেটটাইমআউট কাজ করে না, এবং এটি দুঃখজনক। আমার সম্পর্কে আপনি কী মনে করেন জানি।


কীপ্রেসের পরিবর্তে কীআপ চেষ্টা করুন।
আয়ন টান

-2

@ বালাপটনের উত্তরের ভিত্তিতে:

$(document).on('focus', '[contenteditable]', e => {
	const self = $(e.target)
	self.data('before', self.html())
})
$(document).on('blur', '[contenteditable]', e => {
	const self = $(e.target)
	if (self.data('before') !== self.html()) {
	  self.trigger('change')
	}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.