I set event listener to button and expect new node adding every time the button is pressed, but, in fact, this works only one time. That must be my mistake with ":last" selector which somehow freezes on the same node. How can I fix this?
$("#btnAddWord").on('click', function(){
$('div.input-group:last').after( inputGroup );
});
http://jsfiddle.net/aT82W/
It's because you try to add again and again the same element (instead of a new one). Let's create a new one for each click.
Modified code from your JSFiddle example:
$("#btnAddWord").on('click', function(){
var inputGroup = document.createElement('div');
inputGroup.setAttribute('class','input-group');
inputGroup.innerHTML = '...here your HTML...';
$('div.input-group:last').after( inputGroup );
});
You should use a function that generates new input groups, here you're always referring to the same element (created one time only).
function createInputGroup() {
return $('<div class="input-group">' +
'<span class="input-group-addon">' +
' <input type="checkbox">' +
'</span>' +
'<input type="text" class="form-control" placeholder="New word">' +
'<span class="input-group-addon">' +
' <span class="glyphicon glyphicon-remove-circle"></span>' +
'</span>' +
'</div>');
}
$("#btnAddWord").on('click', function(){
$('div.input-group:last').after( createInputGroup() );
});
Looking at your fiddle link it seems that, inputGroup is no longer available on next click. so try this:
function CreateDiv()
{
var inputGroup = document.createElement('div');
inputGroup.setAttribute('class','input-group');
inputGroup.innerHTML = '<span class="input-group-addon">'+
' <input type="checkbox">'+
'</span>'+
'<input type="text" class="form-control" Placeholder="New word">'+
'<span class="input-group-addon">'+
' <span class="glyphicon glyphicon-remove-circle"></span>'+
'</span>';
return inputGroup;
}
$(document).on("click", "#btnAddWord", function(){
$('div.input-group:last').after( CreateDiv() );
});
$("#btnAddWord").on('click', function(){
var inputGroup = document.createElement('div');
inputGroup.setAttribute('class','input-group');
inputGroup.innerHTML = '<span class="input-group-addon">'+
' <input type="checkbox">'+
'</span>'+
'<input type="text" class="form-control" Placeholder="New word">'+
'<span class="input-group-addon">'+
' <span class="glyphicon glyphicon-remove-circle"></span>'+
'</span>';
$('div.input-group').last().append( inputGroup );
});
you are just moving the same element from place to place (which is the same place by the way).
You need to clone this element by doing
$(inputGroup).clone()
Related
Just like on facebook, I want to make a sidebar that has the names of friends in which the user can click to open up a corresponding message_block that contains a message_tab to open a flyout with the previous messages and form for new ones.
HTML
<div class = "dock">
<div class = "docking_tabs">
</div>
</div>
I have a problem with .append( ) and being able to manipulate the contents inside. This code works fine on the first try. However when I make a new message tab the previously made tab does not respond. Here is what I have:
JavaScript
$('.chat_list').click(function(){
var user_id = $(this).attr('value');
var el = $('<div class = "message_block">'+
'<div class = "message_tab">'+ '</div>' +
'<div class = "message_flyout">' +
'<div class = "message_content">' +
'<div class = "message_header">'+ '</div>' +
'<div class = "conversation_scroll">' +
'<div class = "scroll_content">' + '</div>' + '</div>' +
'<div class = "message_form">' +
"<form method= 'POST' action= 'http://localhost:8000/newtch' accept-charset= 'UTF-8'>" + "<input name='_token' type='hidden' value='2rS54FJZJZhWPplLmBJSH4CsID7Pgec7iPsDtrnm'>" +
'<div class = "message_form">' +
"<input class='input-mini' placeholder='Type a message' name='status' type='text'>" +
'</div>'+
"</form>" +
'</div>'+
'</div>'+
'</div>'+
'</div>');
$('.docking_tabs').append(el);
$('.message_tab').on('click', function(){
$(this).addClass(user_id);
$(this).siblings('.message_flyout').toggle();
});
$('.message_header').on('click', function(){
console.log('clicked');
$(this).closest('.message_flyout').toggle();
});
});
When you do this:
$('.message_tab').on('click', function(){
$(this).addClass(user_id);
$(this).siblings('.message_flyout').toggle();
});
You're not just adding a click handler to the element you just created, you're also adding another click handler to all previously created elements. Which means the "previous tab" now has two click handlers both executing this:
$(this).siblings('.message_flyout').toggle();
Which would essentially cancel one another out.
Instead of adding a new handler every time you create an element, use event delegation to have a single handler for the whole page:
$(document).on('click', '.message_tab', function(){
$(this).addClass(user_id);
$(this).siblings('.message_flyout').toggle();
});
Execute this once when the page loads (instead of in the '.chat_list' click handler). That way there's just one top-level handler for all matching '.message_tab' elements.
So you end up with something more like this:
$('.chat_list').click(function(){
var user_id = $(this).attr('value');
var el = $('<div class = "message_block">'+
'<div class = "message_tab">'+ '</div>' +
'<div class = "message_flyout">' +
'<div class = "message_content">' +
'<div class = "message_header">'+ '</div>' +
'<div class = "conversation_scroll">' +
'<div class = "scroll_content">' + '</div>' + '</div>' +
'<div class = "message_form">' +
"<form method= 'POST' action= 'http://localhost:8000/newtch' accept-charset= 'UTF-8'>" + "<input name='_token' type='hidden' value='2rS54FJZJZhWPplLmBJSH4CsID7Pgec7iPsDtrnm'>" +
'<div class = "message_form">' +
"<input class='input-mini' placeholder='Type a message' name='status' type='text'>" +
'</div>'+
"</form>" +
'</div>'+
'</div>'+
'</div>'+
'</div>');
$('.docking_tabs').append(el);
});
$(document).on('click', '.message_tab', function(){
$(this).addClass(user_id);
$(this).siblings('.message_flyout').toggle();
});
$(document).on('click', '.message_header', function(){
console.log('clicked');
$(this).closest('.message_flyout').toggle();
})
Hi I did some approach here:
Try to replace:
$('.message_tab').on('click', function(){
$(this).addClass(user_id);
$(this).siblings('.message_flyout').toggle();
});
$('.message_header').on('click', function(){
console.log('clicked');
$(this).closest('.message_flyout').toggle();
})
with this:
el.find('.message_tab').on('click', function(){
$(this).addClass(user_id);
$(this).siblings('.message_flyout').toggle();
});
el.find('.message_header').on('click', function(){
console.log('clicked');
$(this).closest('.message_flyout').toggle();
});
Here an example: https://jsfiddle.net/L3xbyeff/1/. Let me know if this is what you need :)
Good luck!
I have this a button which a user can click on which adds a comment box at the bottom of the page. My button html looks like this:
<input type="button" name="inspection_2895_14045_comment" tabindex="-1" value="+" class="commentBtn" onclick="generateComment('Test', 14045,1, this )">
So as you can see it calls a method called generateComment which looks like this:
function generateComment(name, id, isInspection, button){
//get the current button and hide it
var btn = $("a[name='" + button.name + "'");
btn.hide();//doesn't work
var generatedName = '';
if(isInspection){
generatedName = "comment_" + id;
}
else{
generatedName = "section_" + id;
}
var comment = $('#comments');
var genHtml = '<div class="bigDataDiv">' +
' <label class="commentBoxLabels">' + name + '</label>' +
' x' +
' <textarea rows="4" class="commentBox" name=' + generatedName + ' maxlength="200"></textarea>'
'</div>';
comment.append(genHtml);
$('html,body').animate({
scrollTop: $(".bigDataDiv").offset().top},
'slow');
}
All this method does it hide the button, generate the comment div then scroll to the newly created div. This code worked no problem and used to hide the button but now for some reason it doesn't work and the button still shows up
As neokio pointed out, you forgot the closing ], but you are also selecting an anchor tag, when what you want is an input tag.
var btn = $("input[name='" + button.name + "']");
Since button in your generateComment function is a reference to the button you could just use this to set your btn variable:
var btn = $(button);
Then you don't have to worry about putting strings together to make your selector, or what kind of element the button is. Your hide should work no matter what that way.
You forgot the closing ] ...
var btn = $("a[name='" + button.name + "']");
You're also missing a + before the final '</div>';
I am trying to detect the current button click to assign values to its respective textboxes. Each time I select any of the button, it will detect the first button click and assign the value to the first textbox. Meaning to say that, the second and third button values are assigned to the first textbox. The upload_textbox variable is not changing its value.
I did some error testing, when upload_textbox variable enters custom_uploader.on('select', function(), the value stays and will not change. I am not sure on why it doesn't.
What have I done wrong here? Below are my codes:
function dynamic_image( button )
{
var custom_uploader;
$(button).on('click','input.button',function(e)
{
e.preventDefault();
var $clickedInput = $(this);// JQuery Object of section2_2
var clickedInputId = $clickedInput.attr('id'); // section2_2
var upload_textbox = '#' + 'upload_image_' + clickedInputId;
//If the uploader object has already been created, reopen the dialog
if (custom_uploader) {
custom_uploader.open();
return;
}
//Extend the wp.media object
custom_uploader = wp.media.frames.file_frame = wp.media(
{
title: 'Choose Image',
button: {
text: 'Choose Image'
},
multiple: false
});
//When a file is selected, grab the URL and set it as the text field's value
custom_uploader.on('select', function()
{
attachment = custom_uploader.state().get('selection').first().toJSON();
$(upload_textbox).val(attachment.url);
//console.log(upload_textbox);
});
//Open the uploader dialog
custom_uploader.open();
})
}
dynamic_image('#TextBoxesGroup');
HTML
<tr class="form-field">
<th scope="row">
<label for="component1"> Component 1</label>
<br></br>
<input type='button' class="button button-large" value='+' id='addButton'>
<input type='button' class="button button-large" value='-' id='removeButton'>
<input type='button' class="button button-large" value='Get TextBox Value' id='getButtonValue'>
</th>
<td>
<div id='TextBoxesGroup'>
<div id="ImageDiv1">
<input id="section2_1" class="button" type="button" value="Upload Image" name="upload_s2_1"/>
</div>
<div id="TextBoxDiv1">
<label>Title #1 : </label>
<input type='text' id='title1' />
</div>
<div id="DescDiv1">
<label>Description #1 : </label>
<input type='text' id='description1' /><br></br>
</div>
</div>
</td>
</tr>
script
<script type="text/javascript">
$(document).ready(function(){
var counter = 2;
$("#addButton").click(function () {
if(counter>5){
alert("Only 5 components are allowed");
return false;
}
var newTextBoxDiv = $(document.createElement('div'))
.attr("id", 'TextBoxDiv' + counter);
var newDescDiv = $(document.createElement('div'))
.attr("id", 'DescDiv' + counter);
var newImageDiv = $(document.createElement('div'))
.attr("id", 'ImageDiv' + counter);
var newUploadDiv = $(document.createElement('div'))
.attr("id", 'UploadDiv' + counter);
newTextBoxDiv.after().html('<label>Title #'+ counter + ' : </label>' +
'<input type="text" name="textbox' + counter +
'" id="title_section2_' + counter + '" value="" >');
newDescDiv.after().html('<label>Description #'+ counter + ' : </label>' +
'<input type="text" name="descbox' + counter +
'" id="desc_section2_' + counter + '" value="" ><br></br>');
newImageDiv.after().html('<input class="button" type="button" name="upload_s2_' + counter +
'" value="Upload Image" id="section2_' + counter + '" >');
newUploadDiv.after().html('<input type="text" name="image_url_' + counter +
'" id="upload_image_section2_' + counter + '" >');
newUploadDiv.appendTo("#TextBoxesGroup");
newImageDiv.appendTo("#TextBoxesGroup");
newTextBoxDiv.appendTo("#TextBoxesGroup");
newDescDiv.appendTo("#TextBoxesGroup");
counter++;
});
$("#removeButton").click(function () {
if(counter==1){
alert("No more component to remove");
return false;
}
counter--;
$("#TextBoxDiv" + counter).remove();
$("#DescDiv" + counter).remove();
$("#ImageDiv" + counter).remove();
});
$("#getButtonValue").click(function () {
var msg = '';
for(i=1; i<counter; i++){
msg += "\n Textbox #" + i + " : " + $('#textbox' + i).val();
}
alert(msg);
});
});
</script>
Then I suspect this could be the culprit.
//If the uploader object has already been created, reopen the dialog
if (custom_uploader) {
custom_uploader.open();
return;
}
This would always give you instance of first custom_uploader object.
Try to destroy the previous instance and generate new one.
There might be issue with the event binding within dynamic_image method.
Try
$(button).live('click',function(e) (deprecated as of jQuery 1.7 though)
or
$( document ).on( 'click', button, data, function(e)
instead of
$(button).on('click','input.button',function(e)
I hope it helps.
Can you try following.
$(button).change(function(){
//Write code here
});
I have solved my question. The culprit behind this was the custom_uploader mentioned by #Aman. There was a return statement there where it made the function not to take the new value that has been replaced. After doing so, the custom_uploader opens twice because there is two statement of it which it was called. Did it into an if else statement and had it the way I wanted. Below is my updated code.
function dynamic_image( button )
{
var custom_uploader;
var upload_textbox;
$(button).on('click','input.button',function(e)
{
e.preventDefault();
var $clickedInput = $(this);
var clickedInputId = $clickedInput.attr('id');
upload_textbox = '#' + 'upload_image_' + clickedInputId;
//Extend the wp.media object
custom_uploader = wp.media.frames.file_frame = wp.media(
{
title: 'Choose Image',
button: {
text: 'Choose Image'
},
multiple: false
});
//When a file is selected, grab the URL and set it as the text field's value
custom_uploader.on('select', function()
{
attachment = custom_uploader.state().get('selection').first().toJSON();
$(upload_textbox).val(attachment.url);
});
if (custom_uploader) {
custom_uploader.open();
}else
//Open the uploader dialog
custom_uploader.open();
})
}
#Aman, you have mentioned about optimizing it. It seems quite fast at the moment. Maybe if there is a way to optimize it for the better, it would be a great help.
Thank you all, #Regent, #Aman, #Bhushan Kawadkar, #Arindam Nayak, #Raj
I have a form in which I add new file input fields as the user needs. I'm surrounding the input by a div, as so:
<div id="fileinputs">
<div class="myinput">
<label for="PropertyPic01">Photos</label>
<input type="file" name="data[Property][pic01]" id="PropertyPic01">
</div>
</div>
My jQuery code does the following:
//Add Pic link
$('#addPic').click(function(e)
{
if(!window.fotoCtr)
{
window.fotoCtr = 2;
} else
{
window.fotoCtr++;
}
if(window.fotoCtr == 5)
{
$('#addPic').html('');
}
e.preventDefault();
$('div#fileinputs').html($('div#fileinputs').html() +
'<div class="input file">' +
'<input type="file" name="data[Property][pic0' + window.fotoCtr + ']" id="PropertyPic0' + window.fotoCtr + '">' +
'</div><br/>'
);
})
The issue I'm having is that adding another file input field as I do above causes the selected files from other inputs to be removed. Is there anyway to fix this?
Use instead of html() the append() method, this will keep data bound to previous elements as files:
$('div#fileinputs').append(
'<div class="input file">' +
'<input type="file" name="data[Property][pic0' + window.fotoCtr + ']" id="PropertyPic0' + window.fotoCtr + '">' +
'</div><br/>');
I hope this makes sense. I have an onclick and I am trying to write this data for each div with this.
jQuery('.circle_counter_div').each(function() {
var tagtext = '[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]';
})
I am cloning items but I can only write the data for one of them. How do I write data for each cloned item?
So with the above example I want tagtext to equal
[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]
[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]
[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]
Full Code
HTML
<div class="sc_options circle_counter_div" id="clone_this" style="display: block;">
<input type="text" class="circle_size"/>
</div>
<div class="sc_options circle_counter_div" id="clone_this" style="display: block;">
<input type="text" class="circle_size"/>
</div>
<div class="sc_options circle_counter_div" id="clone_this" style="display: block;">
<input type="text" class="circle_size"/>
</div>
<input type="submit" class="sc_options circle_counter_div" id="insert" name="insert" value="<?php _e("Insert", 'themedelta'); ?>" onClick="insertcirclecountershortcode();" style="display:none"/>
Script
// Insert the column shortcode
function insertcirclecountershortcode() {
var tagtext;
var start;
var last;
var start = '[circlecounters]';
var last = '[/circlecounters]';
jQuery('.circle_counter_div').each(function() {
var tagtext = '[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]';
})
var finish = start + tagtext + last;
if (window.tinyMCE) {
window.tinyMCE.execInstanceCommand(window.tinyMCE.activeEditor.id, 'mceInsertContent', false, finish);
//Peforms a clean up of the current editor HTML.t
//tinyMCEPopup.editor.execCommand('mceCleanup');
//Repaints the editor. Sometimes the browser has graphic glitches.
tinyMCEPopup.editor.execCommand('mceRepaint');
tinyMCEPopup.close();
}
return;
}
Extended Answer: After some more information was provided perhaps you're just missing the index and value properties on the loop. Its hard to tell, since little sample code is provided.
$('.test').each(function(i,v) {
var tagtext = $(v).html();
console.log(tagtext);
})
http://jsfiddle.net/4xKvh/
Original Answer:
Use use classes instead of an Id. Id's are only suposed to be used once on a page.
Since there should only be one occurance jQuery is filtering the result down to 1, even though the markup may have multiple elements with that Id on the page. This is to make use of the built-in browser function getElementById().
For proof checkout this jsFiddle
Using the class attribute is more appropriate for what you're trying to do.
jQuery('.clone_this').each(function() {
var tagtext = '[something][/something]';
})
And the markup:
<div class="clone_this"></div>
This will allow jQuery to return an array of elements like you're looking for
This is what I needed... Finally got it working.
tagtext = ' ';
jQuery('#circle_counter_div .circlecounter').each(function() {
tagtext += '[circlecounter rel="' + jQuery('.circle_size').val() + '" datathickness="' + jQuery('.circle_thickness').val() + '" datafgcolor="' + jQuery('.circle_color').val() + '" text="' + jQuery('.circle_text').val() + '" fontawesome="' + jQuery('.font_awesome_icon').val() + '" fontsize="' + jQuery('.circle_font_size').val() + '"][/circlecounter]';
});
var start = '[circlecounters]';
var last = '[/circlecounters]';
var finish = start + tagtext + last;