"change" not working like "click" - javascript

So I have a web page that looks like this to start with, essentially...
<div id="videonotes_container">
<div id="videonotes_information">
<div id="videonotes_name">Name</div>
<div id="videonotes_points">100 points etc</div>
<div id="videonotes_instructions">
Instructions
</div>
**<div id="videonotes_quicklinks">
<!-- this is where the quick links to the past comments go. -->
</div>**
</div>
<div id="videonotes_video">
<div id="videonotes_video_player"></div>
<div id="videonotes_video_player_overlay"></div>
</div>
<div id="videonotes_controls">
<div id="videonotes_start" class="videonotes_videocontrol">-></div>
<div id="videonotes_pause" class="videonotes_videocontrol">::</div>
<div id="videonotes_stop" class="videonotes_videocontrol">STOP</div>
<div id="videonotes_back30" class="videonotes_videocontrol">RW30</div>
<div id="videonotes_forward30" class="videonotes_videocontrol">FF30</div>
</div>
</div>
and the bit in bold is an area which is dynamically populated by javascript after the page has loaded, with a function that looks like this...
function videonotes_addNote(user_note_id, time, note, rating, feedback) {
// add a new div...
var html_fb = "";
var html_hl = "";
html_hl += "<div class=\"videonotes_note_time\">"+time.toFixed(0)+"</div>";
html_hl += "<div class=\"videonotes_note_note\" data-id=\""+user_note_id+"\" contenteditable>"+note+"</div>";
html_hl += "<div class=\"videonotes_note_comments\">"+rating+"</div>";
// iterate over the feedback and add it into the program.
feedback.forEach(function(value) {
html_fb += "<div class=\"videonotes_note_feedback_note\"><span class=\"videonotes_note_feedback_intro\">"+value.username+" ("+value.timestamp+") said</span> "+value.feedback+"</div>";
html_fb += "<div class=\"videonotes_note_feedback_useful\" data-id=\""+value.noteid+"\">";
html_fb += "<div class=\"videonotes_note_feedback_useful_yes videonotes_note_feedback_useful_button\">ACC</div>";
html_fb += "<div class=\"videonotes_note_feedback_useful_no videonotes_note_feedback_useful_button\">NAC</div>";
html_fb += "</div>";
});
// create a new note on the notes box...
var new_note = $('<div/>', { 'class':'videonotes_note' }).appendTo('#videonotes_quicklinks');
// add the headline to the div...
$('<div/>', { 'class':'videonotes_note_headline', 'html': html_hl, 'click':function(){ videonotes_clickNote(this, time); },}).appendTo(new_note);
// and add the feedback
$('<div/>', { 'class': 'videonotes_note_feedback', 'html': html_fb }).appendTo(new_note);
}
You will note there are a few bits created from this - there are onclick events created which will open feedback on this particular note and navigate to a part of a video. This all works just fine, and the onclick events work just fine for the dynamically created elements. The exception is that for each note you should be able to rewrite it in the div, so you can click the div with the note in, it will naviagte to the correct part of the video (works), it iwll open up the feedback (works) and when you EDIT the .videonotes_note_note class it will fire an update using this method:
$('#videonotes_container').on("change", '.videonotes_note_note', function() { videonotes_update_note($(this).data('id'), $(this).value()); })
However this does not work. I have tried $(document) and all other parent, pre loaded divs I can think of but it still doesnt fire that particular event. There is no difference in the way I am creating this listener to the others, and all the clicks work fine, but the change doesnt.
Am I misunderstanding how the change element works?

change event is not supported on the div tag, you can get the list of input on which change event get fired . https://www.w3schools.com/jsref/event_onchange.asp

Related

How can I add a class on Click event

Here is my markup :
<div class="section-dots active-section"></div>
<div class="section-dots"></div>
<div class="section-dots"></div>
<div class="section-dots"></div>
Here is my JavaScript code:
Note, I am building my markup with the following Jquery code, dynamically:
<script>
var count = 1;
var next;
var url;
var elementId;
// First remove all of the dots
$('.section-dots-container').empty();
$('H2').each(function () {
elementId = 'section-' + count;
url = '#section-' + count;
$(this).attr('id', elementId);
$('.section-dots-container').append('<DIV Class="section-dots"></DIV>');
count++;
});
</script>
This is my script for the click event:
<script>
function setActive() {
next = $(this).find('.section-dots');
next.addClass("active-section");
}
</script>
thus it is setActive that should add "active-section" to the Div inside the anchor tag which I am building dynamically. but I not certain if I am doing this correctly.
It seems like it would be easier to just bind the click event to your element in your js code based on its class rather than adding it into your html.
So maybe change markup to include a common class name like:
<div class="section-dots active-section"></div>
<div class="section-dots"></div>
<div class="section-dots"></div>
<div class="section-dots"></div>
And then just bind a click event to all elements with that class:
$('.section').click(function(){
$(this).find('.section-dots').addClass("active-section");
});
I would un-capitalize the DIV and some other things in your code, but this should work if I'm understanding what you want to do.
$('.section-dots').click(function(){
$(this).addClass('active-section');
});
you are using $(this) without passing any parameter to the function.
<script>
function setActive() {
next = $(this).find('.section-dots');
next.addClass("active-section");
}
</script>
useing jquery, select the element you want to add the class to it and use the addClass("class_to_add") function.

Buttons from cloned section not working properly

I'm new to jquery scripts. I managed to clone one section of the form dynamically but my button to display the ckeditor's div in the cloned section is not working. It still listening to the button from the original section and will only show the ckeditor's div(but unable to edit all of them except the original) when the original button was clicked. Here is my code:-
for(i=num; i<value; i++){
var newSlot = $('#slot' + i).clone().attr('id','slot' + (i+1));
newSlot.find('.heading-slot').attr('id', 'ID' + (i+1) + '_slot').html('Slot ' + (i+1)); //add new slot name
newSlot.find('.other_message').hide();
newSlot.find('.select_instruction').on('change', function () {
$(this).next('.other_message').toggle((this.value) == "Other")
});
newSlot.find('.extra_instruction').hide();
//the button here is not working as I wanted
newSlot.find('.btnAdditional').on('click', function(){
$(this).next('.extra_instruction').show();
});
$('#slot' + i).after(newSlot);
}
html code
<div class="col-sm-6">
<button type="button" id="btn_Additional" name="btn_Additional" class="btnAdditional btn btn-info">Additional Instruction</button>
<div class="extra_instruction">
<textarea id="input_add_instruction" name="add_instruction[]" class="form-control"></textarea>
<script>CKEDITOR.replace( 'input_add_instruction' );</script>
</div>
</div>
Can anyone guide me on this?? Please I'm very new to this. Thanks in advances..
The clone function not only clones the html but also the event listeners, instead of cloning try creating your element and adding the event listeners properly.

Append a div outside of the input parent

Im fairly new to javascript and I just can't figure this out despite my attempt in researching. How do I track the change of a input within a div and trigger an append to an outside div? My code goes as follow:
Append h3 with "Pending" once ".image-value" input has a change in value
<!-- APPEND <h3> -->
<h3>Best Overall Costume<div class="pending">Pending</div></h3>
<div>
<div class="select-form">
<img src="images/vote.jpg" data-value="image_value">
<img src="images/vote.jpg" data-value="image_value2">
<img src="images/vote.jpg" data-value="image_value3">
<img src="images/vote.jpg" data-value="image_value4">
<img src="images/vote.jpg" data-value="image_value5">
<!-- Track the change of this input -->
<input type="hidden" class="image-value" name="selected_image" value="">
</div>
</div>
I tried this:
function changeStatus(statusValue) {
$("input",".select-form").val(statusValue).trigger("change");
}
$("input",".select-form").change(function(){
if (!$(this).val()){
$("<div class='pending'>Pending</div>").appendTo($("h3").prev($(this)));
}
});
But that didn't seem to work. Any ideas?
place an empty div where you want your new div and give it an id i.e(<div id='myDiv'><div>) and then append what you want like this.
$( "#myDiv" ).append( "<div class='pending'>Pending</div>" );
You can also check Append Explained
for more explanations.
Thanks.
I've done a couple things here... First, I'm not sure why you had it all in a named function. When you're using event listeners that often isn't necessary.
Then, I don't know what the val check was for, so I reversed it.
Finally, I'm using one(), which only runs once. This case seemed to call for that.
$('.select-form').one('change', 'input', function () {
if ( $(this).val() ) { alert('asdgf');
$("<div class='pending'>Pending</div>")
.appendTo($(this).parent().prev('h3'));
}
});
Fiddle
try this:
$("input",".select-form").on("change", function(){
var $this = $(this);
if (!$this.val()){
var elem = $('<h3>Best Overall Costume<div class="pending">Pending</div></h3>');
$this.parent().parent().before(elem);
}
});
you can also place a check, that if the pending div is already added, not to add it again.
Of course this solution assumes that there are no other nested divs between the target div(before which you want to append) and the input control

jQuery: How to assign the right ID to a button dynamically

I have a JS/jQuery script that adds our leads (web contacts) to the DOM in a for loop. Everything works fine except for one thing. I want the body of the lead to be hidden upon the initial display, and then have a slideToggle button to display or hide the details That means dynamically adding click events to each button as it is created. The entire HTML (HTML and a JSON object mixed into the HTML) of the lead and the slideToggle button are all appended to a node in the DOM in the for loop. Here is the pertinent part of the for loop:
// Hide the body of the lead; just show the title bar and the first line
var dataID = data[i].id
var div = $('#row' + dataID);
var more = $('#more' + dataID);
div.hide();
// Create click event for each "+" button
more.click(function() {
div.slideToggle();
});
But when I click on the "+" button to reveal the details, it opens the last div, not the div I am trying to open. This is true no matter how many leads I have on the page. How do I get the click event to open the right div. If I console.log "div" in the click event, it gives me the ID of the last div, not the one I am clicking on. But if I console.log(div) outside the click event, it has the right ID.
Also, I was unsure whether I needed the "vars" in the loop or if I should declare them outside the loop.
Here is the HTML. It's one lead plus the beginning of the next lead, which I left closed in Firebug
<div id="lead1115">
<div id="learnmore">
<a id="more1115" class="more" href="#">+</a>
</div>
<div id="lead-info">
<div id="leadID">Lead ID# Date: March 27, 2012 11:26 AM (Arizona time)</div>
<div id="company">No company given</div>
<div id="name">Meaghan Dee</div>
<div id="email">
meaghan.dee#gmail.com
</div>
<br class="clearall">
<div>
<div id="row1115" style="display: none;">
<div id="phone">No phone given</div>
<div id="source">www.ulsinc.com/misc/expert-contact/</div>
<div id="cp-name">No channel partner chosen</div>
<br class="clearall">
<div id="location">
No location given
<br>
<strong>IP Address:</strong>
198.82.10.87
<br>
<span>Approximate Location: Blacksburg, Virginia, United States</span>
<br>
</div>
<div id="details">
<strong>Questions/Comments</strong>
<br>
We have the Professional Series Universal Laser Systems (laser cutter), and I wondered how I would order a high power density 2.0 replacement lens.nnThank you
</div>
</div>
</div>
</div>
<div id="learnmore">
<a id="1115|send_message" class="verify" href="#">Verify</a>
<a id="1115|send_message" class="markAsSpam" href="#">Spam</a>
<a id="1115|send_message" class="markAsDuplicate" href="#">Duplicate</a>
</div>
</div>
<br class="clearall">
<div id="lead1116">
<br class="clearall">
Try using .bind (or .on for 1.7+) and the data parameter.
more.bind("click",{target:div},function(e){
e.data.target.show();
}
or
more.on("click",{target:div},function(e){
e.data.target.show();
}
I think your basic problem is that div is common as a variable to all items. You have to separate the div's from each other by, for example, creating a local function and call it for each item. Something like:
function buildMore(div) {
more.click(function() {
div.slideToggle();
});
}
and in the loop call:
addMore(div);
p.s.
Whether you declare your variables inside or outside the loop doesn't matter: you still get the same variables.
This is because div variable gets changed and settles with the last value set in the loop.
Try this:
...
funciton createClick(div) {
return function() { div.slidToggle();
}
more.click( createClick(div) );
...
The variable div doesn't stay frozen with your click handler so it's value will be what it was at the end of the for loop and all click handlers will use the same value (which is what you're seeing).
There are a number of different ways to approach this and I thought all would be educational. Any one of them should work.
Idea #1 - Manufacture the row id from the clicked on more id
Use the id value on the clicked on link to manufacture the matching row ID. Since you create them in pairs, this can be done programmatically like this:
// Hide the body of the lead; just show the title bar and the first line
var dataID = data[i].id
$('#row' + dataID).hide();
$('#more' + dataID).click(function() {
// manufacture the row ID value from the clicked on id
var id = this.id.replace("more", "#row");
$(id).slideToggle();
});
Idea #2 - Use a function closure to "freeze" the values you want
Another way to do that is to create a function and closure that will capture the current value of div:
// Hide the body of the lead; just show the title bar and the first line
var dataID = data[i].id
var div = $('#row' + dataID).hide();
var more = $('#more' + dataID);
function addClick(moreItem, divItem) {
// Create click event for each "+" button
moreItem.click(function() {
divItem.slideToggle();
});
}
addClick(more, div);
Idea #3 - Use the HTML spatial relationship to find the row associated with a more
To make this work, you need to put a common class=lead on the top level lead div like this:
<div id="lead1115" class="lead">
And, a common class on each row:
<div id="row1115" class="row" style="display: none;">
Then, you can use the position relationships to find the row object that is in the same parent lead object as the clicked on more link like this:
// Hide the body of the lead; just show the title bar and the first line
var dataID = data[i].id
$('#row' + dataID).hide();
$('#more' + dataID).click(function() {
// find out common parent, then find the row in that common parent
$(this).closest(".lead").find(".row").slideToggle();
});
Idea #4 - Put the row ID as data on the more link
// Hide the body of the lead; just show the title bar and the first line
var dataID = data[i].id
$('#row' + dataID).hide();
$('#more' + dataID).data("row", "#row" + dataID).click(function() {
// get the corresponding row from the data on the clicked link
var rowID = $(this).data("row");
$(rowID).slideToggle();
});

click() for ClassName

UPDATE: A commenter told me to change some codes, this is the new code and its not working neither.
I'm creating a Facebook-Like chat. It gets the latest messages "Not Read" from a JSON file and it appends the text to an "UL" element vía "LI" into a box. If the box doesn't exist, it creates and attach the text. I want that when I click that div, it hides using margin-bottom negative, and when I click it again it shows by Margin-Bottom:0. Please help me since it's just not working.
function showChat(id){
$(this).animate({marginBottom : "0"}).removeClass("hidden_box").addClass("active_box").removeAttr('onclick').click(function(){
hideChat(Id);
});
}
function hideChat(id){
$(this).animate({marginBottom : "-270px"}).removeClass("active_box").addClass("hidden_box").click(function(){
showChat(Id);
});
}
function getOnJSON(){
//Creating Variables that will be used
var from;var to;var msg_id;var msg_txt;
//Getting the data from the json file
$.getJSON("/ajax/chat.json.php",function(data){
//Repeat for each result
$.each(data.notif, function(i,data){
//Getting a var to info
from = data.from;to = data.to;msg_id = data.id;msg_txt = data.text;
//check if div exists
if ($("#chat_"+from+"_lp").length === 0){
//If not, create the div
$("#boxes").append('<div id="chat_'+from+'_lp" class="chat_box hidden_box clickable_box"></div>');
//Add the senders name
$("#chat_"+from+"_lp").append('<div id="'chat_+from+'_nick" class="chat_name">'+from+'</div>');
//Add the chats UL
$("#chat_"+from+"_lp").append('<ul id="chat_'+from+'_txt" class="chat_txt"></ul>');
//Add the message text
$("#chat_"+from+"_lp").append('<li id="' + msg_id + '">'+ msg_txt+'</li>');
//Add event handler for each div
$('#chat_'+from+'_lp').click(function() {showChat(this);});
//If div exists just add the text
}else{
//Add the message text
$("#chat_"+from+"_txt").append('<li id="' + msg_id + '">'+ msg_txt+'</li>');
//Add event handler for each document
$('#chat_'+from+'_lp').click(function() {showChat(this);});
//Close If
}
//Close data for each item
});
//Close JSON
});
//Close Function
}
UPDATE 2: in order to stop making and appending things, I made an unique HTML string that is going to be appended.
new_chat_string = '<div id="chat_'+from+'_lp" class="chat_box hidden_box clickable_box"><div id="'chat_+from+'_nick" class="chat_name">'+from+'</div><ul id="chat_'+from+'_txt" class="chat_txt"><li id="' + msg_id + '">'+ msg_txt+'</li></ul></div>';
$("#boxes").append(new_chat_string);
use class instead of id
<div id="chat_sender_lp" class="chat_box hidden_box clickable_box sender-click"
then
$('.hidden_box.sender-click').live('click', function(){
$(this).slideToggle(500);
});
After:
$("#boxes").append('<div id="chat_'+from+'_lp" class="chat_box hidden_box clickable_box" ><div id="name">'+from+'</div><ul id="chat_'+from+'_txt" class="chat_txt"><li id="' + msg_id + '">'+ msg_txt+'</li></ul></div>');
Add the event handler for the inserted element:
$('#chat_'+from+'_lp').click(function() { showChat(this) })
"this" passes a DOM reference to itself.
Keep in mind that you're adding: <div id="name"> every time. IDs must be unique. Use a class name instead.
EDIT:
Appending to the DOM is really quite slow. It's actually more efficient to build up your HTML as a string and just insert it in one go. Also, you only really need to stick and ID on the wrapping element. Everything else can be derived from that using a jQuery selector. It helps you write much cleaner code.
Here's the string you need to append:
'<div id="chat_'+msg_id+'" class="chat_box hidden_box clickable_box">
<div class="chat_name">'+from+'</div><ul class="chat_txt"><li>
'+msg_txt+'</li></ul></div>'
If you wanted to select chat name later, you'd use: $('chat_1 .chat_name').html()
It also makes more semantic sense to hook up your click handler to an A tag. So you'd use:
$('#chat_'+msg_id).find('a').click(function() {showChat(this);});
The code is a lot cleaner and easier to follow this way. I hope this helps.

Categories

Resources