Instantly share code, notes, and snippets.

Embed
What would you like to do?
/*!
* jQuery TextChange Plugin
* http://www.zurb.com/playground/jquery-text-change-custom-event
*
* Copyright 2010, ZURB
* Released under the MIT License
*/
(function ($) {
$.event.special.textchange = {
setup: function (data, namespaces) {
$(this).data('lastValue', this.contentEditable === 'true' ? $(this).html() : $(this).val());
$(this).bind('keyup.textchange', $.event.special.textchange.handler);
$(this).bind('cut.textchange paste.textchange input.textchange', $.event.special.textchange.delayedHandler);
},
teardown: function (namespaces) {
$(this).unbind('.textchange');
},
handler: function (event) {
$.event.special.textchange.triggerIfChanged($(this));
},
delayedHandler: function (event) {
var element = $(this);
setTimeout(function () {
$.event.special.textchange.triggerIfChanged(element);
}, 25);
},
triggerIfChanged: function (element) {
var current = element[0].contentEditable === 'true' ? element.html() : element.val();
if (current !== element.data('lastValue')) {
element.trigger('textchange', [element.data('lastValue')]);
element.data('lastValue', current);
}
}
};
$.event.special.hastext = {
setup: function (data, namespaces) {
$(this).bind('textchange', $.event.special.hastext.handler);
},
teardown: function (namespaces) {
$(this).unbind('textchange', $.event.special.hastext.handler);
},
handler: function (event, lastValue) {
if ((lastValue === '') && lastValue !== $(this).val()) {
$(this).trigger('hastext');
}
}
};
$.event.special.notext = {
setup: function (data, namespaces) {
$(this).bind('textchange', $.event.special.notext.handler);
},
teardown: function (namespaces) {
$(this).unbind('textchange', $.event.special.notext.handler);
},
handler: function (event, lastValue) {
if ($(this).val() === '' && $(this).val() !== lastValue) {
$(this).trigger('notext');
}
}
};
})(jQuery);
@MarcusJT

This comment has been minimized.

MarcusJT commented Jun 15, 2010

The "textchange" event setup & teardown bind/unbinds don’t match.

I think the teardown lines should be:
a(this).unbind(“keyup”, a.event.special.textchange.handler);
a(this).unbind(“cut paste input”, a.event.special.textchange.delayedHandler)

You could also improve the code by using namespaced events (http://docs.jquery.com/Namespaced_Events) to do the same with less code:

setup: function () {
a(this).bind(“keyup.hastext”, a.event.special.textchange.handler);
a(this).bind(“cut.hastext paste.hastext input.hastext”, a.event.special.textchange.delayedHandler);
}, teardown: function () {
a(this).unbind(“.hastext”)

@mkelly12

This comment has been minimized.

Owner

mkelly12 commented Jun 15, 2010

Good catch Marcus. Updated.

@mkelly12

This comment has been minimized.

Owner

mkelly12 commented Jun 18, 2010

Add support for contentEditable from http://gist.github.com/443903. Thanks Andre.

@mkelly12

This comment has been minimized.

Owner

mkelly12 commented Sep 7, 2010

Set the lastValue in the setup callback so that tabbing to a input the first time does not incorrectly fire the hasText or changeText event. Thanks dcneiner for pointing this out in https://gist.github.com/568577. I see that nathanhammond had this fix in his fork as well, https://gist.github.com/553602.

@mkelly12

This comment has been minimized.

Owner

mkelly12 commented May 9, 2011

Pass arguments to trigger in an array to fix stricter behavior in jQuery 1.6.

Broken up into two commits because I pasted in the code incorrectly the first time. Sorry.

https://gist.github.com/424774/361f3aea17e41e726bb3a9c3d4b179e49ca75a80
https://gist.github.com/424774/f279b03d73e22305059f590b745618fdb9158771

@softlion

This comment has been minimized.

softlion commented Jul 30, 2011

Hi, i added a textchanged method. See fork https://gist.github.com/1115896

@mkelly12

This comment has been minimized.

Owner

mkelly12 commented Aug 1, 2011

Nice, I'll be sure to point anyone to this fork that needs that functionality.

@thomthom

This comment has been minimized.

thomthom commented Sep 28, 2011

Is the 25ms delay required? I've not tested extensively, but it seems that the text content get around to update even with a delay of 0.

@thomthom

This comment has been minimized.

thomthom commented Sep 29, 2011

Under IE, when you use the Context Menu to delete the selected text, it doesn't trigger the event.
Under Firefox it does trigger however.

@softlion

This comment has been minimized.

softlion commented Sep 29, 2011

I've tryed my textchanged method, works ok with IE 7-9 with the scenario you described.

@thomthom

This comment has been minimized.

thomthom commented Oct 2, 2011

hm... that is odd. Are we really doing the same thing? I uploaded a short video of what I see: http://dl.dropbox.com/u/4791584/textchange.mp4
Notice that when I choose Delete the count doesn't update.

@softlion

This comment has been minimized.

softlion commented Oct 3, 2011

What version of jquery are you using ? Can you push your demo to jsfiddle ? It still works in my case with your scenario.

@thomthom

This comment has been minimized.

thomthom commented Oct 3, 2011

That is example 2 at: http://www.zurb.com/playground/jquery-text-change-custom-event

But trying the plugin locally on my own system with jQuery 1.6.2 - same thing.

@softlion

This comment has been minimized.

softlion commented Oct 3, 2011

Well example 2 (detecting text changes) works on IE7-9 on my system.
Wrote: aaa bbb ccc
Cut: bbb with context menu
Result: Text changed from aaa bbb ccc to aaa ccc

@thomthom

This comment has been minimized.

thomthom commented Oct 3, 2011

Well Cut works for me as well. But it's Delete that does not trigger an event.

@softlion

This comment has been minimized.

softlion commented Oct 3, 2011

ok you are right.
Seems to be a bug in IE9.
See the comment here: http://msdn.microsoft.com/en-us/library/gg592978(v=vs.85).aspx

@thomthom

This comment has been minimized.

thomthom commented Oct 3, 2011

hmm... interesting. So it work on older version? And older versions use attachEvent... I wonder if it would work under IE9 if one used attachEvent. Might be something to mention to the jQuery team..?

@thomthom

This comment has been minimized.

thomthom commented Oct 3, 2011

No :( attachEvent did not make a difference.

@garrettlancaster

This comment has been minimized.

garrettlancaster commented Mar 16, 2012

This is a great plugin, but it doesn't seem to work on dynamically added inputs. The bind works fine, but the textchange event is never triggered.

@mkelly12

This comment has been minimized.

Owner

mkelly12 commented Mar 16, 2012

Right, it only works with regular event binding. It does not work with .live(), .on(), or .delegate().

@whiteskull

This comment has been minimized.

whiteskull commented Jul 2, 2012

thx for this plugin, but how I can use it with - live

@mkelly12

This comment has been minimized.

Owner

mkelly12 commented Jul 2, 2012

whiteskull: It only currently works with bind. Would be awesome to see a rewrite that supports live as well.

@chaoflow

This comment has been minimized.

chaoflow commented Nov 19, 2012

Thank you very much for your plugin, it is already very useful!

I write a plugin that maintains form state: disable/enable save/reset buttons and modified/saved classes on the form. I listen to "textchanged" with one() (no selector) to mark the form as changed. In case the text returns to its original content / the content at the last savepoint, it would be great to get a unchanged event.

@chaoflow

This comment has been minimized.

chaoflow commented Nov 19, 2012

comment to my own comment: that in itself would only be useful if there is only one text field and the implementation is probably rather expensive.

@JProbe

This comment has been minimized.

JProbe commented Feb 21, 2013

I tried your plugin in IE8 it sems you can bind hastext and textchange events through bind() but not with on() and on() is preferred approach over bind() as it is deprecated. Wondering if someone has seen similar issue

@jeanph01

This comment has been minimized.

jeanph01 commented Jul 15, 2013

What can I say ? Thanks ! :-)

@arthur-s

This comment has been minimized.

arthur-s commented Aug 21, 2013

It seems that there're bug in Firefox and Chrome in Ubuntu 12.04
Textchange worked perfectly in all browsers for Ubuntu linux, but 2 days ago it stopped to work both in Firefox and Chrome at the same time. But in Opera it continued to work, very strange.
Then i upgraded my browsers, and the problem has gone.

@ranadeep47

This comment has been minimized.

ranadeep47 commented Sep 14, 2013

Doesn't work on latest version of chrome
29.0.1547.66 (Official Build 220848)

@imkevinxu

This comment has been minimized.

imkevinxu commented Nov 15, 2013

Ditto, the demos on this page seem to be broken for Chrome Version 31.0.1650.48 http://zurb.com/playground/jquery-text-change-custom-event

@vasilakisfil

This comment has been minimized.

vasilakisfil commented Feb 2, 2014

It doesn't work on Chrome and Firerox.. any idea?

@Zeokat

This comment has been minimized.

Zeokat commented Mar 3, 2014

I was testing into Chrome and not works. Anyways i will work on your code, you saved Zeokat tons of work.

@KiruNiku

This comment has been minimized.

KiruNiku commented Mar 12, 2014

An event is not performed.

1.$("textarea").val("test1\ntest2");
2.selected delete textarea value;

@baldmountain

This comment has been minimized.

baldmountain commented Apr 2, 2014

Because it uses keyup to decide if it should trigger it won't work with multi keystroke characters like ü or many Chinese characters. It triggers on the first keystroke rather than on the full character after the second keystroke.

@espellcaste

This comment has been minimized.

espellcaste commented Apr 23, 2014

The examples are not working on this page http://zurb.com/playground/jquery-text-change-custom-event

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment