My page is moderately complicated and I'm fairly sure its the jquery acting weird. So i'll add the relevant content first and if anyone needs more info let me know and I'll provide it.
The premise is that there is a div which holds keyword bubbles. These bubbles have a tooltip (qTip plugin) with relevant info that you can select and deselect. Sometimes keywords have overlapping relevant info so when one is deselected all others need to be deselected at the same time. This list of bubbles is built dynamically via ajax and can continue to be added on to the page live.
The problem is that some of the check boxes don't uncheck when I click on them, but if I click on the same one in another tooltip it works... which also now lets the original one work just fine. I have no idea why some work and others dont. I figure it has to do with the way the live onlick function binding and/or selectors are written.
The following function writes the html content of the tooltip based on a json object, so just assume the content is there. The jquery code at the bottom is the function I have bound to the checkboxes.
function constructSpecializationsHTML(data){
var html = '';
for(i = 0; i < data.specializations.length; i++){
if(data.specializations[i].name != ''){
html += "<span class='is-specialization-line'>";
html += "<input class='is-specialization-checkbox' type='checkbox' name='" + data.specializations[i].name + "' checked='" + isSpecializationChecked(data.specializations[i].name) + "'/>";
html += "<span>" + data.specializations[i].name + "</span>";
html += "</span><br />";
} else {
html += "This keyword is not known in our ontology";
}
}
return html;
}
$(document).on("click", ".is-specialization-checkbox", function(){
var $checkboxs = $(".is-specialization-checkbox[name='" + $(this).attr("name") + "']")
$checkboxs.prop("checked", !$checkboxs.prop("checked"));
});
Firstly, when the click event fires the "checked" property has already been changed, meaning that the states of your checkboxes are different.
Changing
!$checkboxs.prop("checked")
To
$(this).prop("checked")
Solves that.
Secondly when you have only displayed one tooltip your select is only returning one checkbox. If you display all the tooltips before checking or unchecking it returns the correct number. My guess is that qTip isn't adding the html for the tooltip to the DOM until it is displayed.
That's why not all your similarly named checkboxes are unchecking though (At least I think that's it!)
$(document).on("click", ".is-specialization-checkbox", function(){
var $checkboxs = $(".is-specialization-checkbox[name='" + $(this).attr("name") + "']")
$checkboxs.not($(this)).prop("checked", false);
});
changed this to $(this) - that way it is the specific checkbox that was clicked that is getting excluded from the deselection.
Related
Here is my first question here, I've been looking for an small clue on many researches but didn't found any piece of answer, hope it's not a silly thing.
I'll try to be straight: I'm working on a website dealing with xml files (data is stored in an array then displayed and fully editable).
Until now and despite some troubles I figured out, everything works fine.
I loop on my array to get all the required string then create jQuery object (such as $("<input id='xxx' value='yyy' />") that I appendTo a specific div).
At first start, I have an empty #insertXml div (written in my html).
One my xml files parsed and my array ready, I dynamcically create a #content div appended to my #insertXml, then for each index I'll have its key written in a #keyInput" div (dynamic insert, only once), then 1st value in a #lang1 div (still dynamic insert), 2nd in #lang2 div, etc.
lang1, lang2, etc are variables, so it's written:
$("<input .../>").appendTo("#"+langN);
where langN changes on each loop.
Everything works FINE!... at 1st display :/
The trouble is, when I'm using my function that creates new data.
I work first on a modal window, to retrieve user values through the listener function, then pass it to another function that pushes it in my array.
I debugged it, that works, my array is correctly updated.
Then I want to simply refresh my page, so I try, the same way I did previously for my whole data, to append a few inputs.
It works then correctly on my #keyInput div, but NOT on my #lang divs !?!?!
No matter how I try (even forgetting jQuery and using html document.xxx functions), no way.
While debugging, all my variables are OK, it just does nothing when doing the "appendTo", except once for the keyInput div.
I tried then to remove the #content div and relaunch the whole displayInit() method (heavy operation but, just to see) and same damn problem: only the #keyInput is correctly refreshed.
The only thing I've read that may be interesting, is that dynamically created elements (through script) are not registered in the DOM, so it can't be found.
BUT in that case, none of my display attempts should work, so?
In advance, THANK YOU very much for taking care about my nightmare.
Attached: my html + JS function.my DOM
function displayInsert() {
var firstLang = stripXmlExtension(paths[0]); // same keys on every language, so we grab the 1st one
var lastKeyIndex = mapXml[firstLang].key.length - 1;
var keyToInsert = mapXml[firstLang].key[lastKeyIndex]; // == last insertion
var inputKey = "<input size=35 type=text id=k" + lastKeyIndex + " value=" + stripHTML(keyToInsert.replace(/ /g, " ")) + " readonly />";
// while appending tag to the HTML content page, we add a dblclick listener that will morph the input into a textarea when double dblclicked
$(inputKey).css("margin-bottom", "15px").dblclick(function (e) {
e.preventDefault();
tempEditId = $(this).attr('id');
$(".modal-body").html("<textarea cols='65' rows='10' id='txt" + $(this).attr('id') + "'>" + $(this).val() + "</textarea>");
$("#modalEdit #btn-correct").css("display", "none");
$("#modalEdit").modal({backdrop: "static"});
}).appendTo("#keyInput");
for (var i = 0; i < paths.length; i++) {
var lang = stripXmlExtension(paths[i]);
var lastValueIndex = mapXml[lang].value.length - 1;
var valueToInsert = mapXml[lang].value[lastValueIndex]; // == last insertion
var inputValue = "<input size=35 type=text id=" + lang + "---" + lastValueIndex + " value=" + stripHTML(valueToInsert.replace(/ /g, " ")) + " readonly />";
// while appending tag to the HTML content page, we add a dblclick listener that will morph the input into a textarea when double clicked
$(inputValue).css("margin-bottom", "15px").dblclick(function (e) {
e.preventDefault();
tempEditId = $(this).attr('id');
$(".modal-body").html("<textarea cols='65' rows='10' id='txt" + $(this).attr('id') + "'>" + $(this).val() + "</textarea>");
$("#modalEdit #btn-correct").css("display", "none");
$("#modalEdit").modal({backdrop: "static"});
}).appendTo("#" + lang);
}
}
OMG, I'm ashamed.
My problem came from an input generated in a modal window that took the same id that was duplicated...
I was hoping it would be a little more complicated ^^
Solved!
Problem
I have some dynamically generated HTML (using JavaScript) that contains a form with some radio buttons in it. I added event listeners (using "change") to all of the radio buttons to call a function whenever their value is changed. I am already aware that this event only triggers when a button's "checked" value goes from false to true, and not the other way around.
To simplify my code, I've wrapped the label tags around the input tags to avoid having to generate a bunch of unique id's for my radio buttons. However, when the label tags are wrapped around the radio inputs rather than sitting in the same scope as the radio inputs, the "change" event listener does not respond, even when clicking directly on the button itself.
Examples
I put together a jsfiddle example to show what I'm talking about. JS Fiddle Example
The first group (that doesn't work) is generated this way:
for (var i = 0; i < 3; i++)
{
var label = document.createElement("label");
var radio = document.createElement("input");
radio.setAttribute("type", "radio");
radio.setAttribute("name", "group1");
radio.addEventListener("change", function()
{
alert("group1 changed!")
}, false);
label.appendChild(radio);
label.innerHTML += "Radio " + (i + 1);
var br = document.createElement("br");
g1.appendChild(label);
g1.appendChild(br);
}
And the second group (that does work) is generated this way:
for (var i = 0; i < 3; i++)
{
var radio = document.createElement("input");
radio.setAttribute("type", "radio");
radio.setAttribute("name", "group2");
radio.setAttribute("id", "g2r" + i);
radio.addEventListener("change", function()
{
alert("group2 changed!")
}, false);
var label = document.createElement("label");
label.setAttribute("for", "g2r" + i);
label.innerHTML = "Radio " + (i + 1);
var br = document.createElement("br");
g2.appendChild(radio);
g2.appendChild(label);
g2.appendChild(br);
}
Question
Is this an known bug or something? And is there some kind of workaround? I'd like to keep the wrapped labels because it's easier to generate, and I think it's cleaner, but not at the expense of functionality, obviously.
Thank you!
I removed the line:
label.innerHTML += "Radio " + (i + 1);
from your jsFiddle and that fixes the issue. The reason this is breaking your code is that when you use innerHTML to add something to inside another element, what you're really doing is replacing all of the contents of that element. Sure, when you use += you're keeping what was there before and adding to it, but you're still essentially copying the contents out, adding to them, and then creating NEW DOM ELEMENTS for all the html you're adding back in -- whether it's the old contents or the new. This means that any handlers bound to the old contents will be lost, since you're overwriting them with new DOM elements.
If you replace that line with this:
label.appendChild(document.createTextNode("Radio " + (i + 1)));
That'll append the new text node you're creating without removing and recreating any of your existing elements, so your handlers will still be there! Here's a working jsFiddle: http://jsfiddle.net/335cQ/13/.
radio.setAttribute("id", "rb");
<style>
#rb
{
z-index:5;
}
</style>
I am using chosen plugin for a multiple select and I want to dynamically display all the selected options somewhere in the page.
I am able to show them, however, I also want to remove them if someone deselects/removes them. This is what I am struggling with.
My code till now looks like
$(".chosen-select").chosen({max_selected_options: 5}).change(function() {
var bStr = "#home-summary-right";
var htmlContent = $("#home-summary-right").html();
$(".search-choice").find("span").each(function() {
$(bStr).html("" + htmlContent);
toAppend = '<span>' + $(this).text() + '</span>';
$(bStr).append(toAppend);
});
});
Okay
Otherwise, is there any way to disable removing of elements once they are select in the multiple select? There is that cross, to which I can do display none, but I still don't know how can i disable the backspace from removing the elements.
Okay, I fixed it.
I used setTimeout in combination with bunch of other things.
The problem was after change, the inner html would return the same content as before... So I called an event after pretty much everything was done. Works super smooth!
I want to make a transition page that stands as a break between the Login page & the main page.
The Page contains nothing but The list of names ... So, I don't want to make it to be a drop down list ... I want the page to be filled with a scrollable list.
I tried making a div with some buttons inside it, but it doesn't look good. So, do you have any ideas on how can I make the page looks better, or whether I should use 2 divs inside each other & modify them using CSS?
This is what I made:
JS:
function GetClassesList(data) {
var classes = (typeof data) == 'string' ? eval('(' + data + ')') : data;
$('#ClasssesList').empty();
for (var i = 0; i < classes.length; i++) {
var text = '<button class="BigDiv" value="' + classes[i].Cls_ID + '" >' + classes[i].Cls_Name + '</button>';
$('#ClasssesList').append(text);
}
$("#ClasssesList").bind('click', 'button.BigDiv',CallLink());
}
HTML:
<div id="ClasssesList" ></div>
Thanks a lot.
It seems like your code works fine... If I understand correctly, you could define the height and width of #ClassesList and set the overflow to scroll in the CSS. Then, you can format the buttons to appear however you wanted when you are formatting the html inside of the for loop.
I don't understand exactly what you are looking for though. Maybe if you could clarify a bit.
I got this javascript loop which generates a unordered list with maybe 50 list items.. Now I want to put a button in every list item which stores the content in a database. Think retweet.
I figured out a way which is put the button and the content from the listitem within a hidden input in the loop but that seems like a bad shortcut. Like this:
html += "<form action=\"add.php\" method=\"post\"><input type=\"hidden\" value=\"" + listitem + "\" name=\"item\"\/>";
html += "<input type=\"submit\" value=\"repost\" \/><\/form>";
Using jQuery seems much more subtle and more like the right thing to do. I've gotten this far:
$("button").click(function()
var value = ($(this).text());
$.post('add.php',{value:value};
});
With a button in the loop instead of the input. But I can't even get the jQuery to response to the button click. Is there anyway this is possible or should I just go with the shortcut?!
The loop =
var html = "<li><h2 class=\"postTitle\">" + title + " <\/h2>";
html += "<p id=\"postText\" class=\"postText\">" + text + "</p></li>";
$('#Content').append($(html));
And the html where the loop ends up:
<ul id="list">
<div id="Content">
</div>
</ul>
From the code above the jQuery selector being used ("button") will not match anything in your code as you've used an input for the button; try:
$("input[type=submit]").click(function () {
...
});
Ideally use a more targeted selector as I presume you don't want every submit button to do this :)
Try giving your button a unique id?
resulting in:
$('#myId').click(function(){
//your code here
});
That is much better to specify.
You can also try to give it a class and an id
$('.myClass').click(function(){
var myButton = $(this).attr('id');
if(myButton == 'myId'){ do this} else if(myButton == 'myOtherId'){do this}
});
that way you can handle several buttons in one function, and if there are many buttons if statements will make your code look all messed up and you can use a select case :)
First, if you send your data via AJAX $.post, you should prevent submitting a form:
$("button[type=submit]").click(function(oEvent) {
oEvent.preventDefault();
// or in the end of handler
return false;
});
Second, <input> and <button> elements will return nothing in $(elem).text(), to get a value you should use $(elem).val() method.
Third, use the id attribute for HTML elements, this will help you manage DOM easier.