I want to make an alert when a div's innerText changes:
myDiv.addEventListener("change", function() {
if (myDiv.innerText != "some text")
alert('innerText has changed.');
},false);
Does not work.
myDiv.addEventListener("DOMCharacterDataModified", function (event) { // ... add your code he }, false);
use DOMCharacterDataModified to detect innerText change event
Posted on behalf of the OP.
I found a solution:
// THIRD FUNCTION (changes the text)
var i = 0;
function thirdFUN(){
i++;
var popo = document.getElementById('myDiv');
popo.innerText = i;
}
setInterval(thirdFUN, 500);
//---------------------------------------------------------------
// JQUERY
/*var popo = $('#myDiv');
$('#myDiv').bind("DOMSubtreeModified",function(){
if (popo.html() == "10")
console.log('changed');
});
*/
//---------------------------------------------------------------
// PURE JS
window.onload = function(){
var popo = document.querySelector('#myDiv');
var observer = new MutationObserver(function(mutations){
mutations.forEach(function(mutation){
console.log(mutation.type); // <- It always detects changes
if (popo.innerHTML == "10"){
alert('hello');
}
});
});
var config = {characterData: true, subtree: true};
observer.observe(popo, config);
//observer.disconnect();
}
This is also a JS Fiddle.
The change event isn't specified to fire at any point the text changes. It fires only when the textarea loses focus (the user clicks away or tabs away). So your event will only fire when this happens.
Aside from continually checking the value of the textarea with an interval, there is no elegant way to do this (to my knowledge).
Note in this fiddle that the change event only fires after the textarea has lost focus.
See this answer for more info...
Can't comment on the top answer since not enough reputation, but according to MDN, Mutation Events (so including DOMCharacterDataModified) were deprecated and shouldn't be used anymore. Luckily, you can get the same thing with Mutation Observers now.
try
document.addEventListener("change", function() ......
Related
I have this function where I toggle a class on click, but also append HTML to an element, still based on that click.
The problem is that now, I'm not listening to any DOM changes at all, so, once I do my first click, yup, my content will be added, but if I click once again - the content gets added again, because as far as this instance of jQuery is aware, the element is not there.
Here's my code:
(function($) {
"use strict";
var closePluginsList = $('#go-back-to-setup-all');
var wrapper = $('.dynamic-container');
$('#install-selected-plugins, #go-back-to-setup-all').on('click', function(event) {
$('.setup-theme-container').toggleClass('plugins-list-enabled');
if ( !wrapper.has('.plugins-container') ){
var markup = generate_plugins_list_markup();
wrapper.append(markup);
} else {
$('.plugins-container').hide();
}
});
//Below here, there's a lot of code that gets put into the markup variable. It's just generating the HTML I'm adding.
})(jQuery);
Someone suggested using data attributes, but I've no idea how to make them work in this situation.
Any ideas?
You could just do something like adding a flag and check for it before adding your markup.
var flag = 0;
$('#install-selected-plugins, #go-back-to-setup-all').on('click', function(event) {
$('.setup-theme-container').toggleClass('plugins-list-enabled');
if ( !wrapper.has('.plugins-container') ){
var markup = generate_plugins_list_markup();
if(flag == 0){
wrapper.append(markup);
flag = 1;
}
} else {
$('.plugins-container').hide();
}
});
If you want to add element once only on click then you should make use of .one() and put logic you want to execute once only in that handler.
Example :
$(document).ready(function(){
$("p").one("click", function(){
//this will get execute once only
$(this).animate({fontSize: "+=6px"});
});
$("p").on("click", function(){
//this get execute multiple times
alert('test');
});
});
html
<p>Click any p element to increase its text size. The event will only trigger once for each p element.</p>
I am looking for a way to manage the events. I have a hover function for element A, and click function for element B. I want to disable A`s hover function temporary while the second click of B.
I am looking for a way that not necessary to rewrite the hole function of A inside of B. Something very simply just like "Store and Disable Event, Call Stored Function"
I found some technique like .data('events') and console.log. I tired but failed, or maybe I wrote them in a wrong way.
Please help and advice!
$(A).hover();
$(b).click(
if($.hasData($(A)[0])){ // if A has event,
//STORE all the event A has, and disable
}else{
//ENABLE the stored event for A
}
);
Try this
var hoverme = function() {
alert('Hover Event Fired');
};
$('.A').hover(hoverme);
var i = 0;
$('.B').on('click', function(){
if(i%2 === 0){
// Unbind event
$('.A').off('hover');
}
else{
// Else bind the event
$('.A').hover(hoverme);
}
i++;
});
Check Fiddle
I think that what you want to do is something like this (example for JQuery 1.7.2):
$("#a").hover(function(){alert("test")});
$("#a")[0].active=true;
$("#b").click(function(){
if($("#a")[0].active){
$("#a")[0].storedEvents = [];
var hoverEvents = $("#a").data("events").mouseover;
jQuery.each(hoverEvents , function(key,handlerObj) {
$("#a")[0].storedEvents.push(handlerObj.handler);
});
$("#a").off('hover');
}else{
for(var i=0;i<$("#a")[0].storedEvents.length;i++){
$("#a").hover($("#a")[0].storedEvents[i]);
}
}
$("#a")[0].active = ($("#a")[0].active)==false;
});
JSFiddle Example
But there are a couple of things that you must have in consideration:
This will only work if you add the events with JQuery, because JQuery keeps an internal track of the event handlers that have been added.
Each version of JQuery handles data("events") differently, that means that this code may not work with other version of JQuery.
I hope that this helps.
EDIT:
data("events") was an internal undocumented data structure used in JQuery 1.6 and JQUery 1.7, but it has been removed in JQuery 1.8. So in JQuery 1.8 the only way to access the events data is through: $._data(element, "events"). But keep in mind the advice from the JQuery documentation: this is not a supported public interface; the actual data structures may change incompatibly from version to version.
You could try having a variable that is outside the scope of functions a and b, and use that variable to trigger the action to take in function b on function a.
var state;
var a = function() {
if(!state) {
state = true;
// Add hover action and other prep. I'd create a third function to handle this.
console.log(state);
};
var b = function() {
if(state) {
state = false;
// Do unbinding of hover code with third function.
} else {
state = true;
// Do whatever else you needed to do
}
}
Without knowing more about what you're trying to do, I'd try something similar to this.
It sounds like you want to disable the click hover event for A if B is clicked.
$("body").on("hover", "#a", function(){
alert("hovering");
});
$("#b").click( function(){
$("body").off("hover", "#a", function() {
alert("removed hovering");
});
});
You can use the jQuery off method, have a look at this fiddle. http://jsfiddle.net/nKLwK/1/
Define a function to assign to hover on A element, so in b click, call unbind('hover') for A element and in second click on b element define again a function to hover, like this:
function aHover(eventObject) {
// Todo when the mouse enter object. You can use $(this) here
}
function aHoverOut(eventObject) {
// Todo when the mouse leave the object. You can use $(this) here
}
$(A).hover(aHover, aHoverOut);
// ...
$(b).click(function(eventObject) {
if($.hasData($(A)[0])){ // if A has event,
$(A).unbind('mouseenter mouseleave'); // This is because not a event hover, jQuery convert the element.hover(hoverIn, hoverOut) in element.bind('mouseenter', hoverIn) and element.bind('mouseleave', hoverOut)
}else{
$(A).hover(aHover, aHoverOut);
}
});
There are provably better ways to do it, but this works fine, on document ready do this:
$("#a")[0].active=false;
$("#b").click(function(){
$("#a")[0].active = ($("#a")[0].active)==false;
if($("#a")[0].active){
$("#a").hover(function(){alert("test")});
}else{
$("#a").off('hover');
}
});
JSFiddle example
You can use .off function from jQuery to unbind the hover on your "a" element.
function hoverA() {
alert('I\'m on hover');
}
$('#a').hover( hoverA );
var active = true;
$('#b').on('click', function(){
if(active){
$('#a').off('hover');
active = false;
} else{
$('#a').hover(hoverA);
active = true;
}
});
Live demo available here : http://codepen.io/joe/pen/wblpC
I want to trigger an event handler once per each actual change in an input field. For example, to validate (per keypress) entry of a credit card number (the change must be on each change so debouncing/throttling is not the answer).
I cannot use input alone as IE9 will not trigger this event from backspaces or cut/delete.
I cannot use keyup alone as this does not handle changes from a mouse (eg. pasting).
I cannot use change because this only fires on blur.
I can do $('input').bind('input keyup', handler) but this will fire two separate events most of the time. Assume that the handler is expensive and running it twice is unacceptable.
I can wrap the handler so that it only runs if the current value is different to the last checked but is there a better way?
What you are doing with checking the last input is what you need to do.
This is one way you can do it to store the last value.
function handler(){
var tb = jQuery(this);
var currentValue = tb.val();
if (tb.data("lastInput") !== currentValue) {
tb.data("lastInput", currentValue);
console.log("The current value is " + currentValue);
}
}
$('input').bind('input keyup', handler);
jsFiddle
You could always extend jQuery if you really do not want that logic in your function. It is a bunch more code, but one method.
(function(){
$.fn.oneinput = function(callback) {
function testInput(){
var tb = jQuery(this);
var currentValue = tb.val();
if (tb.data("lastInput") !== currentValue ) {
tb.data("lastInput",currentValue );
if(callback) {
callback.call(this)
};
}
return this;
}
jQuery(this).bind("keyup input", testInput);
};
}(jQuery));
$('input').oneinput( function(){ console.log(this.value); });
jsfiddle
I think the you have to use setInterval to moniter the change in the text box
try this demo
objTextBox = document.getElementById("trackChange");
oldValue = objTextBox.value;
console.log(oldValue);
function track_change()
{
if(objTextBox.value != oldValue)
{
oldValue = objTextBox.value;
console.log("changed")
}
}
setInterval(function() { track_change()}, 100);
Note: I don't personally think that this is the best solution.But I cant find a better and at leat it will work for sure in every case keyboard or mouse change ;)
Try this
$('input').bind('keyup cut paste', function (event) {
console.log('value changed');
});
Fiddle http://jsfiddle.net/sXvK2/1/
If you don't need the handler to return a value, you can make it return false so that it doesn't fire up a second time.
What about
$el.bind('input', handler);
$el.bind('keyup', handler);
...
I need to get the newly focussed element (if any) while executing an onBlur handler.
How can I do this?
I can think of some awful solutions, but nothing which doesn't involve setTimeout.
Reference it with:
document.activeElement
Unfortunately the new element isn't focused as the blur event happens, so this will report body. So you are gonna have to hack it with flags and focus event, or use setTimeout.
$("input").blur(function() {
setTimeout(function() {
console.log(document.activeElement);
}, 1);
});
Works fine.
Without setTimeout, you can use this:
http://jsfiddle.net/RKtdm/
(function() {
var blurred = false,
testIs = $([document.body, document, document.documentElement]);
//Don't customize this, especially "focusIN" should NOT be changed to "focus"
$(document).on("focusin", function() {
if (blurred) {
var elem = document.activeElement;
blurred = false;
if (!$(elem).is(testIs)) {
doSomethingWith(elem); //If we reached here, then we have what you need.
}
}
});
//This is customizable to an extent, set your selectors up here and set blurred = true in the function
$("input").blur(function() {
blurred = true;
});
})();
//Your custom handler
function doSomethingWith(elem) {
console.log(elem);
}
Why not using focusout event? https://developer.mozilla.org/en-US/docs/Web/Events/focusout
relatedTarget property will give you the element that is receiving the focus.
I have an anchor tag on my page, I want an event attached to it, which will fire when the display of this element change.
How can I write this event, and catch whenever the display of this element changes?
This is my way of doing on onShow, as a jQuery plugin. It may or may not perform exactly what you are doing, however.
(function($){
$.fn.extend({
onShow: function(callback, unbind){
return this.each(function(){
var _this = this;
var bindopt = (unbind==undefined)?true:unbind;
if($.isFunction(callback)){
if($(_this).is(':hidden')){
var checkVis = function(){
if($(_this).is(':visible')){
callback.call(_this);
if(bindopt){
$('body').unbind('click keyup keydown', checkVis);
}
}
}
$('body').bind('click keyup keydown', checkVis);
}
else{
callback.call(_this);
}
}
});
}
});
})(jQuery);
You can call this inside the $(document).ready() function and use a callback to fire when the element is shown, as so.
$(document).ready(function(){
$('#myelement').onShow(function(){
alert('this element is now shown');
});
});
It works by binding a click, keyup, and keydown event to the body to check if the element is shown, because these events are most likely to cause an element to be shown and are very frequently performed by the user. This may not be extremely elegant but gets the job done. Also, once the element is shown, these events are unbinded from the body as to not keep firing and slowing down performance.
You can't get an onshow event directly in JavaScript. Do remember that the following methods are non-standard.
IN IE you can use
onpropertychange event
Fires after the property of an element
changes
and for Mozilla
you can use
watch
Watches for a property to be assigned
a value and runs a function when that
occurs.
You could also override jQuery's default show method:
var orgShow = $.fn.show;
$.fn.show = function()
{
$(this).trigger( 'myOnShowEvent' );
orgShow.apply( this, arguments );
return this;
}
Now just bind your code to the event:
$('#foo').bind( "myOnShowEvent", function()
{
console.log( "SHOWN!" )
});
The code from this link worked for me: http://viralpatel.net/blogs/jquery-trigger-custom-event-show-hide-element/
(function ($) {
$.each(['show', 'hide'], function (i, ev) {
var el = $.fn[ev];
$.fn[ev] = function () {
this.trigger(ev);
return el.apply(this, arguments);
};
});
})(jQuery);
$('#foo').on('show', function() {
console.log('#foo is now visible');
});
$('#foo').on('hide', function() {
console.log('#foo is hidden');
});
However the callback function gets called first and then the element is shown/hidden. So if you have some operation related to the same selector and it needs to be done after being shown or hidden, the temporary fix is to add a timeout for few milliseconds.