I want to trigger an event once a DIV is populated from the back, 2 nodes are inserted in my DIV. I'm using this:
$(function () {
var xml = document.querySelector('#XML');
xml.addEventListener("DOMNodeInserted", function (ev) {
doSomething();
}, false);
});
This works when the XML div is populated once the doc is loaded or reloaded.
At some point, the user clicks a button and the div#XML is populated dynamically without a reload and even though a DOM node is inserted into my element, nothing happens.
How can I trigger "doSomething()" when my div changes?
Your code works fine. Like you can see in Mutation events and the relative compatibility HERE:
$(function () {
$('#XML').on("DOMNodeInserted", function (ev) {
console.log('DO SOMETHING');
});
$('#btnAdd').on('click', function(e) {
$('#XML').append($('<p>', {text: 'this is a new paragragh'}));
});
});
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<div id="XML"></div>
<button id="btnAdd">Add a paragragh to div</button>
Following code might be the one you looking for. It will look for changes in your div every 1000 milliseconds, you can change that according to your requirements. If your div has some text initially then update the oldVal accordingly.
$('#XML').change(function(){
alert("div has changed!");
// replace with your actions
});
var oldVal = "";
function InputChangeListener()
{
if($('#XML').val() != oldVal)
{
oldVal = $('#XML').val();
$('#XML').change();
}
}
setInterval(InputChangeListener, 1000);
Related
I am trying to develop some code to allow the user show/hide a block level element by clicking a button.
The HTML structure is like below
<div class="chat_container"><a class="crm" href="https://google.com" target="_blank">Chat?</a><button id="close_chat"><</button></div>
I have written a click() function for #close_chat which amongst other things changes the ID of the button to #open_chat. I then use the on() method on #open_chat to modify some classes and ids on various elements. In isolation both these methods work, however when combined they don't work. I have noticed that when I click #close_chat even though the ID changes to #open_chat the original event is still attached to the button. After doing some search I suspected the issue might have been related to events bubbling up, but now I am not so sure, still I added event.stopPopagation() to my click function and I can see it appears to be called correctly. I have also tried using the one() method, this appeared to get closer to the behavior I was expecting at the DOM level but still didn't working
My expected behavior is the click() function is called when the user clicks #close_chat, the event is then unbound allowing the .on() event to be called on #open_chat. Id than of course have to reset the original functionality. My code looks like this
$(document).ready(function () {
var close = "<button id='close_chat'><</div>";
var container = $("<div />");
container.addClass("chat_container");
var crmChat = $("<a />");
crmChat.addClass("crm");
crmChat.attr("href", "https://google.com");
crmChat.attr("target", "_blank");
crmChat.text("Chat?");
console.log(crmChat);
console.log(container);
$(container).insertAfter("#heading");
$(container).prepend(crmChat);
$(close).insertAfter(crmChat);
$("#close_chat").click(function (event) {
$("#close_chat").removeAttr("id").attr("id", "open_chat");
event.stopPropagation();
alert(event.isPropagationStopped());
//return false;
});
$(".chat_container").on("#open_chat", "button", function () {
//$(".crm_chat_container").addClass("animate-open").removeClass("animate-close");
$("#open_chat").html(">").removeAttr("id").attr("id", "reopen");
//event.stopPropagation();
});
});
any help is greatly appreciated
Sam
edit, I have now updated my code to look like so
//onclick function for our close button
$("#close_chat").click(function (event) {
attachClosedChatListner();
});
function attachOpendChatListener() {
$(".chat_container").on("click","#open_chat", function () {
$("#open_chat").removeAttr("id").attr("id", "close_chat");
$("#close_chat").html("<")
$(".crm_chat_container").removeClass("animate-close").addClass("animate-open");
});
//attachClosedChatListner();
}
function attachClosedChatListner() {
$("#close_chat").off('click');
$("#close_chat").removeAttr("id").attr("id", "open_chat");
$("#open_chat").html(">")
$(".chat_container").removeClass("animate-open").addClass("animate-close");
//attachOpendChatListener();
}
What about re-attaching the event?
$("#close_chat").click(function (event) {
$("#close_chat").removeAttr("id").attr("id", "open_chat");
attachOpenChatListener();
event.stopPropagation();
alert(event.isPropagationStopped());
//return false;
});
function attachOpenChatListener() {
$("#close_chat").off('click');
$(".chat_container").on("#open_chat", "button", function () {
//$(".crm_chat_container").addClass("animate-open").removeClass("animate-close");
$("#open_chat").html(">").removeAttr("id").attr("id", "reopen");
//event.stopPropagation();
});
}
I managed to work this out, the click function was causing the problem
//onclick function for our close button
$("#close_chat").click(function (event) {
attachClosedChatListner();
});
I've replaced it with .on and it works now
$(".crm_chat_container").on("click", "#close_chat", function (event) {
$("#close_chat").off('click');
$("#close_chat").removeAttr("id").attr("id", "open_chat");
$("#open_chat").html(">");
$(".crm_chat_container").removeClass("primo-animate-open").addClass("animate- close");
attachCloseChatListener();
event.stopImmediatePropagation();
});
function attachCloseChatListener() {
$(".crm_chat_container").on("click", "#open_chat", function (event) {
$("#open_chat").off('click');
$(".crm_chat_container").removeClass("primo-animate-close").addClass("primo-animate-open");
$("#open_chat").removeAttr("id").attr("id", "close_chat");
$("#close_chat").html("<");
event.stopImmediatePropagation();
});
}
on thing is my click events appears to be firing multiple times, that is after clicking my buttons a few times I see several click events in dev tools.
Anyway, thanks for putting me on the right path
I have created a on change method for a select box of my project. On selecting particular option it is basically showing and hiding a div which is perfectly working fine. Now, my problem is when first time page is loading this show and hide not working for first default section of form. Can I make this onchange function also working when page load first time.
$('.contact-form').on('change', (e) => {
var selectedId = $(e.currentTarget).val();
var listofforms = $("#discount").data("display-for").split(",");
if (listofforms.indexOf(selectedId) !== -1) {
$("#discount").collapse('show');
}
else {
$("#discount").collapse('hide');
}
});
Here you go with a solution
function changeMethod(selectedId) {
var listofforms = $("#discount").data("display-for").split(",");
if (listofforms.indexOf(selectedId) !== -1) {
$("#discount").collapse('show');
}
else {
$("#discount").collapse('hide');
}
}
changeMethod($('.contact-form').val())
$('.contact-form').on('change', (e) => {
changeMethod($(e.currentTarget).val());
});
You need to move your code outside the change event, so I have kept your existing code within a method changeMethod.
Then call the method from to places
From you change event method
OnLoad of the JS file
Is it possible can I make my on change trigger on page load
Yes, you will just need to change your on change event from e.currentTarget to this as on page load e.currentTarget will be null, but this always points to the current element like:
$('.contact-form').on('change', function() {
var selectedId = $(this).val();
// Your other logic here
});
and to trigger this change event on page load, simply add .change() at last like:
$('.contact-form').on('change', function() {
var selectedId = $(this).val();
// Your other logic here
}).change(); //<---- here
Given the following markup, I want to detect when an editor has lost focus:
<div class="editor">
<input type="text"/>
<input type="text"/>
</div>
<div class="editor">
<input type="text"/>
<input type="text"/>
</div>
<button>GO</button>
EDIT: As the user tabs through the input elements and as each editor div loses focus (meaning they tabbed outside the div) add the loading class to the div that lost focus.
This bit of jquery is what I expected to work, but it does nothing:
$(".editor")
.blur(function(){
$(this).addClass("loading");
});
This seems to work, until you add the console log and realize it is triggering on every focusout of the inputs.
$('div.editor input').focus( function() {
$(this).parent()
.addClass("focused")
.focusout(function() {
console.log('focusout');
$(this).removeClass("focused")
.addClass("loading");
});
});
Here is a jsfiddle of my test case that I have been working on. I know I am missing something fundamental here. Can some one enlighten me?
EDIT: After some of the comments below, I have this almost working the way I want it. The problem now is detecting when focus changes to somewhere outside an editor div. Here is my current implementation:
function loadData() {
console.log('loading data for editor ' + $(this).attr('id'));
var $editor = $(this).removeClass('loaded')
.addClass('loading');
$.post('/echo/json/', {
delay: 2
})
.done(function () {
$editor.removeClass('loading')
.addClass('loaded');
});
}
$('div.editor input').on('focusin', function () {
console.log('focus changed');
$editor = $(this).closest('.editor');
console.log('current editor is ' + $editor.attr('id'));
if (!$editor.hasClass('focused')) {
console.log('switched editors');
$('.editor.focused')
.removeClass('focused')
.each(loadData);
$editor.addClass('focused');
}
})
A bit more complicated, and using classes for state. I have also added in the next bit of complexity which is to make an async call out when an editor loses focus. Here a my jsfiddle of my current work.
If you wish to treat entry and exit of the pairs of inputs as if they were combined into a single control, you need to see if the element gaining focus is in the same editor. You can do this be delaying the check by one cycle using a setTimeout of 0 (which waits until all current tasks have completed).
$('div.editor input').focusout(function () {
var $editor = $(this).closest('.editor');
// wait for the new element to be focused
setTimeout(function () {
// See if the new focused element is in the editor
if ($.contains($editor[0], document.activeElement)) {
$editor.addClass("focused").removeClass("loading");
}
else
{
$editor.removeClass("focused").addClass("loading");
}
}, 1);
});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/8s8ayv52/18/
To complete the puzzle (get your initial green state) you will also need to also catch the focusin event and see if it is coming from the same editor or not (save the previous focused element in a global etc).
Side note: I recently had to write a jQuery plugin that did all this for groups of elements. It generates custom groupfocus and groupblur events to make the rest of the code easier to work with.
Update 1: http://jsfiddle.net/TrueBlueAussie/0y2dvxpf/4/
Based on your new example, you can catch the focusin repeatedly without damage, so tracking the previous focus is not necessary after all. Using my previous setTimeout example resolves the problem you have with clicking outside the divs.
$('div.editor input').focusin(function(){
var $editor = $(this).closest('.editor');
$editor.addClass("focused").removeClass("loading");
}).focusout(function () {
var $editor = $(this).closest('.editor');
// wait for the new element to be focused
setTimeout(function () {
// See if the new focused element is in the editor
if (!$.contains($editor[0], document.activeElement)) {
$editor.removeClass("focused").each(loadData);
}
}, 0);
});
Here's what worked for me:
$(".editor").on("focusout", function() {
var $this = $(this);
setTimeout(function() {
$this.toggleClass("loading", !($this.find(":focus").length));
}, 0);
});
Example:
http://jsfiddle.net/Meligy/Lxm6720k/
I think you can do this. this is an exemple I did. Check it out:
http://jsfiddle.net/igoralves1/j9soL21x/
$( "#divTest" ).focusout(function() {
alert("focusout");
});
I want to detect a change in the input field when i select a value from the box like in the picture below.
html:
<input type="text" class="AgeChangeInput" id="range"/>
js:(not working)
<script>
$(document).ready(function()
{
alert("Hello");
$("#range").bind('input', function()
{
alert("done");
});
});
</script>
I also tried live on functions but they didn;t work too.
Your date selection box should fire a change event, then you only need to capture it:
$(function () {
$('#range').change(function () {
...
});
});
If the selection box doesn't fire the event, you'll need to trick the dom. Something like:
$(document).ready(function () {
// Asuming your selection box opens on input click
$('#range').click(function () {
$('.special-box-class').click(fireRangeEvent);
});
// Now the firing function
function fireRangeEvent() {
...
}
});
Hope it works
Try to use this code
changeDate - This event is fired when the date is changed.
$('#range').datepicker().on('changeDate', function(ev) {
//example of condition
if (ev.date.valueOf() > checkout.date.valueOf()) {
//make action here
alert('Here');
}
});
I'm trying to write a web app which replaces the context menu (right-click menu) with my own customized ones. I want it so that when the user clicks on a table row, they get one certain context menu and when they click on the background of the page, they get a different one.
I have already written the menus and gotten them working. The problem comes in when trying to figure out how to get the background's menu to show ONLY when clicking on the background and how to get the table row's menu to show when that is clicked.
I tried using document.body.oncontextmenu for the body and and setting the oncontextmenu function for each table row, but the body's oncontextmenu function overrides the row's so I get the wrong menu. The menu for the table rows DOES work if I stop using the body's menu, so that's not the issue.
I could be using the wrong events, so is there a different event for just the background (and not the elements on top of the background)? Or a way to "prioritize" the events so the table row's function takes precedence?
This is how the code looks:
var tableMenu;
var bodyMenu;
window.onload = function()
{
bodyMenu = new rightClickMenu("bodyMenu");
document.body.oncontextmenu = function() { bodyMenu.show(); tableMenu.hide(); }
bodyMenu.add("Add Entry", function()
{
alert("ADD");
});
tableMenu = new rightClickMenu("tableMenu", "tblSims");
simRows = getElementsByClassName("trSimRow");
for (var i in simRows)
simRows[i].oncontextmenu = function() { tableMenu.show(this.id.substring(2)); bodyMenu.hide(); }
tableMenu.add("Delete Entry", function(mac)
{
alert("DELETE");
});
document.body.onclick = function()
{
bodyMenu.hide();
tableMenu.hide();
};
}
You can capture the target element, e.g.:
$('*').click(function(e) {
alert(e.target);
alert(e.target.tagName);
if(e.target.tagName == 'html') {
// show background menu
}
});
You have to work with the Javascript Event Propagation model. What happens is that your click event is automatically passed down the layers of objects on a page that have been registered as event listeners, unless you explicitly tell it to stop, try something like this:
function setupClickHandlers()
{
document.getElementsByTagName('body')[0].onclick = doBodyMenu;
document.getElementById('tableID').onclick = doTableMenu;
}
function doBodyMenu()
{
//do whatever it does
}
function doTableMenu(e)
{
//do whatever it does
//stop the event propagating to the body element
var evt = e ? e : window.event;
if (evt.stopPropagation) {evt.stopPropagation();}
else {evt.cancelBubble=true;}
return false;
}
This should deal with the way each browser handles events.
$( document ).ready(function() {
var childClicked = false;
// myContainer is the nearest container div to the clickable elements
$("#myContainer").children().click(function(e) {
console.log('in element');
childClicked = true;
});
$("#myContainer").click(function(e){
if(!childClicked) {
console.log('in background');
e.preventDefault();
e.stopPropagation();
}
childClicked = false;
});
});
#myContainer {
width:200px;
height:200px;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="myContainer" style="">
link
<div style="width:50px;height:50px;background-color: white;">
another link
</div>
</div>