I am using a script to generate custom styled dropdowns out of my selects. Basically it creates a list out of the selects and hides the original select making it much easier to style than a <select> allows.
So the basic setup is like this
<div id="formdiv">
<form method="get" name="search" action="samepage">
inputs
</form>
content from form
I want the wrap section to be generated without refreshing the form part that way the dropdodwns dont keep disappearing and reappearing when the page loads.
here is my code for creating the dropdowns ( any performance tuning suggestions are welcome :) )
function createDropDown() {
var selects = $("select.createdrop");
var idCounter = 1;
selects.each(function() {
var dropID = "dropdown_" + idCounter;
var source = $(this);
var selected = source.find("option[selected]");
var options = $("option", source);
source.after('<dl id="' + dropID + '" class="dropdown"></dl>');
var imgtype = '<img src="images/transpx.gif" class="srcimg '+selected.text().toLowerCase()+'" />'
$("#" + dropID).append('<dt>'+imgtype + selected.text() + '<span class="value">' + selected.val() + '</span><img src="images/select-down-arrow.png" class="down-arrow" /></dt>');
$("#" + dropID).append('<dd><ul></ul></dd>');
options.each(function() {
$imgclasstxt = $(this).text().toLowerCase();
var srcimg = '<img src="images/transpx.gif" class="srcimg '+$imgclasstxt+'" width="10px"/>';
$("#" + dropID + " dd ul").append('<li>'+srcimg + $(this).text() + '<span class="value">' + $(this).val() + '</span></li>');
});
idCounter++;
});
}
and here is the code for selecting an option and submiting the form
$(".dropdown dd ul a").click(function() {
var dl = $(this).closest("dl");
var dropID = dl.attr("id");
var text = $(this).attr("id");
var source = dl.prev();
var typeicon = '<img src="images/transpx.gif" class="srcimg '+text.toLowerCase()+'" />'
$("#" + dropID + " dt a").html(typeicon+''+text+'<img src="images/select-down-arrow.png" class="down-arrow" />');
$("#" + dropID + " dd ul").hide();
var value = $(this).children("span.value").html();
source.val(value);
$(this).addClass('selected');
$('body').css('cursor','wait');
document.search.submit();
});
You're modifying the DOM a lot with this code. If it's slow, try dropping as many DOM changes as possible into a string first and then inserting it. You're also doing repeat selects in some places. Example:
$("#" + dropID).append('<dt>'+imgtype + selected.text() + '<span class="value">' + selected.val() + '</span><img src="images/select-down-arrow.png" class="down-arrow" /></dt>');
$("#" + dropID).append('<dd><ul></ul></dd>');
Could change to:
var html = '<dt>'+imgtype + selected.text() + '<span class="value">' + selected.val() + '</span><img src="images/select-down-arrow.png" class="down-arrow" /></dt><dd><ul></ul></dd>'
$("#" + dropID).append(html);
Related
I am adding rows to a table dynamically using the following function. Upon a row click the table disappears and another div is generated and populated dynamically. It was all working perfectly till 2 hours ago, when suddenly without me changing any code it stopped. I am not sure if the following code is sufficient enough for someone to give me an answer but does anyone see any particular reason this will stop working all of the sudden ?
var setupProjectListTable = function (ipProject, table, tableContainer) {
$('#' + table + ' tr').hover(function() {
$(this).addClass('hover');
}, function() {
$(this).removeClass('hover');
});
var title = ipProject.getTitle();
var desc = ipProject.getDesc();
var applicableDegrees = ipProject.getApplicableDegreeList();
var keywordList = ipProject.getKeywordList();
$('#' + table + ' tbody').append(
'<tr id = "' + title + '">' +
'<td>' + title + '</td>' +
'<td>' + desc + '</td>' +
'<td>' + applicableDegrees + '</td>' +
'<td>' + keywordList + '</td></tr>'
);
$("#" + title).click( function(e) {
e.preventDefault();
$('#' + tableContainer).hide();
generateProjectDetails(ipProject);
});
};
It's simple. click() Only affects existing elements but not added elements.
so use on():
$("tbody").on('click', '#' + title, function(e) {
e.preventDefault();
$('#' + tableContainer).hide();
generateProjectDetails(ipProject);
});
Here is my HTML:
<td>
aaaa <b>(97113)</b>
</td>
Here is my JS:
var row_Value = '';
var row_ValueTmp = '';
var aHref = '';
var aClass = '';
var aTip = '';
var manufactererIdAndAliasHtml = '';
$("#batchform tbody tr td:nth-child(3)").dblclick(function(e){
e.preventDefault();
aHref = $(this).find('a').attr('href');
aClass = $(this).find('a').attr('class') || '';
aTip = $(this).find('a').attr('atip') || '';
row_Value = $(this).find('a').text().replace(/"/g, """);
row_ValueTmp = '<div><input type="text" name="tempName" id="tempName" value="'
+ row_Value + '" style="width:90%">'
+ '</div><div id="row_msg"></div>';
$(this).find('a').remove();
manufactererIdAndAliasHtml = $(this).html();
$(this).prepend(row_ValueTmp);
$("#tempName").focus().blur(function(){
var manuId = $(this).parent().parent().find('b').text();
manuId = parseInt( manuId.replace('(','').replace(')','').trim() );
// console.log( manuId );
var msgLayer = document.getElementById("row_msg");
msgLayer.innerHTML = '<font color= "green"><?=$this->GetTranslation("Please wait...");?></font>';
$.ajax({
type: "POST",
url: "ajaxupdate.php",
data:{ tempName: $(this).val(), id: manuId },
dataType: "json",
success: function(re)
{
if(re.message != 'Success'){
msgLayer.innerHTML = '<font color="red">' + re.message + '</font>';
}
$("#tempName").parent().parent().html(
'<a atip="' + aTip + '" class="' + aClass + '" href="' + aHref + '">'
+ $("#tempName").val() + '</a>'
+ manufactererIdAndAliasHtml);
return false;
}
});
});
});
$("#batchform tbody tr td:nth-child(3)").click(function(e){
row_Value = $("#tempName").val();
$("#tempName").parent().parent().html( '<a atip="' + aTip + '" class="' + aClass + '" href="' + aHref + '">' + row_Value + '</a>'
+ manufactererIdAndAliasHtml);
});
Now it has a problem, when I click mouse in input element, the click event will be fired, I want it not fired. Because I don't want the edit status to be changed when I click the input.
Here is the things I've tried but not working:
$("#batchform tbody tr td:nth-child(3):not(:has(input))").click(function(){
console.log('still fired');
});
$("#batchform tbody tr td:nth-child(3)").live('filter', function() {
return $(this).children('input').length == 0;
}).click(function(){
console.log('still fired');
});
e.stopPropagation(); can do the trick for you..
can be inserted after e.preventDefault();
this will prevent the event from bubbling up in DOM tree.
additional information can be found at Jquery API
You probably need:
e.stopImmediatePropagation();
It should stop click from firing on the td element.
Description: Keeps the rest of the handlers from being executed and prevents the event from bubbling up the DOM tree.
$("#batchform tbody tr td:nth-child(3)").off("click").on("click",function(e){
row_Value = $("#tempName").val();
$("#tempName").parent().parent().html( '<a atip="' + aTip + '" class="' + aClass + '" href="' + aHref + '">' + row_Value + '</a>' + manufactererIdAndAliasHtml);
});
try this code snippet.
I'm creating a drop down with three sub menus, so a main dropdown with publishers, a sub menu with authors (which are within that publisher) and a sub menu to authors containing the years they've been published. So hover over publisher, see authors in that publisher.
It worked fine but i've changed it to improve performance so instead of appending to the DOM each time i've been storing up the values in a variable and then appending to the DOM, however i'm now getting an error
cannot call method find of null
relating to the line:
var author = ulauthors.find('li.author[data-value="' + authorval + '"]');
Any ideas how i fix it, i guess because i'm not appending until near the end it can't find the element?
var target = $('#listpublishers');
$(info.genres).each(function (i) {
var genreval = this.genre;
var catval = this.genreGroup;
$(this.publishers).each(function (j) {
var publisherval = this.publisher;
var ulauthors = null;
var publisher = target.find('>li.publisher[data-value="' + publisherval + '"]');
var ulyears = null;
var publisherstring = '';
var targetstring = '';
var ulauthorstring = '';
var authorstring = '';
var ulyearstring = '';
//if publisher does not exist create it else find it
if (publisher.size() == 0) {
targetstring += '<li class="publisher" data-value="' + publisherval + '"><a onclick="gotoSubMenu">' + publisherval + '</a>';
target.append(targetstring)
publisherstring += '<ul class="sub-menuoos" data-title="publishers></ul>';
publisher.append(publisherstring)
} else {
ulauthors = publisher.find('>ul');
}
$(this.authors).each(function () {
var authorval = this.author + ' (' + genreval + ')';
var author_val = this.author;
var author = ulauthors.find('li.author[data-value="' + authorval + '"]');
if (author.size() == 0) {
ulauthorstring += '<li class="author" data-value="' + authorval + '"><a onclick="gotoSubMenu">' + authorval + '</a>';
ulauthors.append(ulauthorstring)
authorstring += '<ul class="sub-menuoos" data-title="authors></ul>';
author.append(authorstring);
} else {
ulyears = author.find('>ul');
}
$(this.publishedYears).each(function () {
var yearval = this;
var year = ulyears.find('li.year[data-value="' + yearval + '"]');
if (year.size() == 0) {
var id = ++count;
ulyearstring += '<li class="year" data-value="' + yearval + '"><a class="item" id="year"' + id + '"data-year="' + yearval + '" data-publisher="' + publisherval + '" data-author+"' + author_val + '" data-genre="' + genreval + '">' + yearval + '</a>';
ulyears.append(year);
}
});
});
});
});
});
I'm trying to show div#options_holder and create some elements inside it by using this code:
var counter = 1;
$('#choices').on("change", ":checkbox", function(e) {
var theName = $(this).attr('name');
var theID = $(this).attr('id');
var isChecked = $(this).prop("checked");
var input, button, append = "";
$("#options_holder").show();
input = capitalize(theName) + '<input name="input_' + theName + '[]" id="' + theID + '" value="" placeholder="' + capitalize(theName) + '" />';
button = '<button type="button" class="add-size">Nuevo ' + capitalize(theName) + '</button>';
append = counter === 1 ? input += button : input;
$("#options_holder").append(append);
counter++;
console.log("You changed " + theName + ", with an id of " + theID + ", its checked property is: " + isChecked);
});
But it does not work since div#options_holder remains hidden and elements aren't created, is something wrong? It's supposed that those should happen any time I mark a checkbox, if I unmark in the other hand the process should be reverted meanind div#options_holder will be hidden and any element inside it should be destroyed, what's wrong?
Making sure that your selectors work and your IDs are correct are often easily overlooked. Glad we could help you find your typing mistake :-)
Working code fiddle: http://jsfiddle.net/pXJpr/
HTML:
<div id="choices">
<input type="checkbox" name="testName" id="testId" />
</div>
<div id="options_holder" style="display:none;">
</div>
JS:
var counter = 1;
$('#choices').on("change", ":checkbox", function(e) {
var theName = $(this).attr('name');
var theID = $(this).attr('id');
var isChecked = $(this).prop("checked");
var input, button, append = "";
$("#options_holder").show();
input = capitalize(theName) + '<input name="input_' + theName + '[]" id="' + theID + '" value="" placeholder="' + capitalize(theName) + '" />';
button = '<button type="button" class="add-size">Nuevo ' + capitalize(theName) + '</button>';
append = counter === 1 ? input += button : input;
$("#options_holder").append(append);
counter++;
console.log("You changed " + theName + ", with an id of " + theID + ", its checked property is: " + isChecked);
});
function capitalize(s) {
return s;
}
Well, I have a table with multiple text nodes I'm getting through the .text() function and linking to another table with one row that I'm using as a timeline.
I tried to input in a single td of the text values that corresponds to the correct data, but I only managed to grab the last value I in my loop, instead of getting them all. Here is my code:
var tHold, divLine, id, dataTitle, dataDescription;
$(".class1").each(function(){
tHold = $(this);
$(".class2").each(function(){
if ($(this).text() == tHold.attr("value")){
if($('#1').children("div#" + tHold.attr("name")).length == 0){
dataTitle = '<div class="r">' + $(this).text() + '</div><br/>';
dataDescription = '<div class="t">' + $(this).parent().children(".x").text() + ': ' + $(this).parent().children(".y").text() + ' (' + $(this).parent().children(".z").text() + ')' + '</div>';
divLine = $('<div id="' + tHold.attr("name") + '" class="b" value="' + tHold.attr("value") + '"></div>');
divLine.append(dataTitle);
divLine.append(dataDescription);
$("#1").append(divLine);
}
if($('#2').children("div#id" + tHold.attr("name")).length == 0){
dataTitle = '<div class="r">' + $(this).text() + '</div><br/>';
dataDescription = '<div class="t">' + $(this).parent().children(".x").text() + ': ' + $(this).parent().children(".y").text() + ' (' + $(this).parent().children(".z").text() + ')' + '</div>';
divLine = $('<div id="des' + tHold.attr("name") + '" class="c" value="' + tHold.attr("value") + '"></div>');
divLine.append(dataTitle);
divLine.append(dataDescription);
$("#2").append(divLine);
}
}
});
});
It's been simplified and cut out of a whole context , but all that matters is there. How can I set dataDescription to be multiple divs with diferent values instead of just the last I loop through?