I have a jsfiddle that replace a td value with a select with 2 values: http://jsfiddle.net/B47km/
When i click the td, the select appears, but when i'm going to see the option elements the click event of the td throws and i can't show the options. How can i solve this?
The HTML:
<table>
<td class="test">1</td>
</table>
The js code:
$(function () {
$(".test").click(function (e) {
e.stopPropagation();
var currentEle = $(this);
var value = $(this).html();
select = '<select class="select-dorsal form-control" type="text">'
+'<option name="1" value="1">1</option>'
+'<option name="2" value="2">2</option>'
+'</select>';
$(currentEle).html(select);
});
});
Fixed it for you http://jsfiddle.net/B47km/3/ This will replace the cell content just once not every time you click on it.
$(function () {
$(".test").click(function (e) {
var currentEle = $(this);
var value = $(this).html();
if ($(this).find('select').length === 0)
{
select = '<select class="select-dorsal form-control" type="text">'
+'<option name="1" value="1">1</option>'
+'<option name="2" value="2">2</option>'
+'</select>';
$(currentEle).html(select);
}
});
});
There's probably a better way (I am a bit rusty on JQuery) but
if (!$(e.target).hasClass('test')) {
return
}
To see if the click event came from the td or the select seems to fix the plnkr.
Use jQuery one() method , which will only listen the event once
$(function () {
$(".test").one('click',function (e) {
e.stopPropagation();
var currentEle = $(this);
var value = $(this).html();
select = '<select class="select-dorsal form-control" type="text">'
+'<option name="1" value="1">1</option>'
+'<option name="2" value="2">2</option>'
+'</select>';
currentEle.html(select);
});
});
Fiddle Demo
Although you've not said explicitly, I'm guessing you're trying to implement a click to change, select a new value and then put that back in (removing the select). In which case:
$(function () {
$('.test').click(function (e) {
var td = $(this);
var select = $(document.createElement('select')).attr('name', 'select_name').attr('class', 'select-dorsal form-control'),
curVal = parseInt(td.get('text'));
for(var i = 0; i <= 5; i++) {
select.append('<option value="' + i + '"' + (curVal == i ? ' selected="selected"' : '') + '>' + i + '</option>');
}
td.html(select);
select.on('click', function(e) { e.stopPropagation(); });
select.on('change', function(e) {
var newVal = parseInt(this.options[this.selectedIndex].value);
td.html(newVal);
});
});
});
http://jsfiddle.net/B47km/10/
Related
I need to select first option of select with jQuery. My code is a bit complex and can't figure out how to make it work. Thanks
Html:
'sortingHtml': '<select id="bc-sf-filter-top-sorting-select">{{sortingItems}}</select>'
Javascript:
BCSfFilter.prototype.buildFilterSorting = function() {
if (bcSfFilterTemplate.hasOwnProperty('sortingHtml')) {
jQ(this.selector.topSorting).html('');
var sortingArr = this.getSortingList();
if (sortingArr) {
// Build content
var sortingItemsHtml = '';
for (var k in sortingArr) {
sortingItemsHtml += '<option value="' + k +'">' + sortingArr[k] + '</option>';
}
sortingItemsHtml = '<option disabled="disabled" selected>Sort by</option>' + sortingItemsHtml
var html = bcSfFilterTemplate.sortingHtml.replace(/{{sortingItems}}/g, sortingItemsHtml);
jQ(this.selector.topSorting).html(html);
// Set current value
jQ(this.selector.topSorting + ' select').val(this.queryParams.sort);
}
}
};
Code to select the first option:
$("#bc-sf-filter-top-sorting-select").val($("#bc-sf-filter-top-sorting-select option:first").val());
$("#bc-sf-filter-top-sorting-select option:first").prop("selected", true);
This is my HTML
<div class="form-group">
<label>Categories</label>
<button type="button" onclick="createContainer(availableCategories,'','.categoriesWrapper','Categories')" class="btn btn-default">+</button>
<div class="categoriesWrapper">
</div>
</div>
Inside I'm adding more divs with 'child' class with this function:
function createContainer(datasource, selectedItem, wrapper, name) {
var maxFields = 10;
var $container = $('<div style="margin-top:5px;" class="child" />');
var $select = $("<select class='form-control littleSpace' name='" + name + "'/>");
var $button = $("<button type='button' class='delete btn btn-default ' '>-</button>");
if ($(wrapper).children().length < maxFields) {
for (var itemId in datasource) {
//check to see if the option is the selected one
var isItemSelected = selectedItem && selectedItem === itemId;
var $option = null;
//create each option
if (isItemSelected == true) {
$option = $('<option value="' + itemId + '" selected>' + datasource[itemId] + '</option>');
}
else {
$option = $("<option value='" + itemId + "'>" + datasource[itemId] + "</option>");
}
//append option to select
$select.append($option);
}
$container.append($select);
$container.append($button);
$(wrapper).append($container);
}
};
Everything works great until now, but when I try to delete one o those divs and div content...it won't work. This is what I've tried:
$('.categoriesWrapper').on('click', 'delete', function () {
$(this).parent.remove();
});
Please help me
Pass class with . to make it work .delete inside click function as well as per #Rayon noticed change parent to parent()
$('.categoriesWrapper').on('click', '.delete', function () {
$(this).parent().remove();
});
I'm using Eric Hynds jQuery MultiSelect Widget that is being populated from a javascript file. The issue is that either selection adds to both sides. Option 1-3 should only add to Main1-3, same for option/Main 4-6. Please see my fiddle of how it works and the issue http://jsfiddle.net/3u7Xj/112/
I think it would be eaisiest to break it out something like
var lbl = $("#MDCselect").val();
if (number1.checked) {...
('.holder').append...
var lbl2 = $("#ClinicalSelect").val();
if (number2.checked) {...
('.holder2').append...
currently
$(document).ready(function () {
$(".multiselect").multiselect({
header: "Choose up to 5 areas total",
click: function (event, ui) {
var number1 = $("#MDCselect").children(":checked").length,
number2 = $("#Clinicalselect").children(":checked").length;
if (ui.checked && ((number1 + number2 >= 5) || $(this).children(":checked").length >= 5)) {
return false;
}
var lbl = ui.value;
if (ui.checked) {
var ctrl = '<input type="checkbox" name="chk" checked="checked" class="chk" id="' + lbl.replace(/[^a-z0-9\s]/gi, '').replace(/[,\s]/g, '') + '">';
$("[id^=id]:checked").each(function () {
$(this).nextAll('.holder:first').append('<div>' + ctrl + lbl + '</div>');
});
} else {
$("[id^=id]:checked").each(function () {
$(this).nextAll('.holder:first').find('#' + lbl.replace(/[^a-z0-9\s]/gi, '').replace(/[,\s]/g, '')).parent().remove();
})
}
},
selectedList: 5
});
$(".checkers").click(function () {
if (!$(this).is(':checked')) {
$(this).nextAll('.holder:eq(0)').find('div input').parent().remove();
} else {
var checkedOnes = $('#MDCselect').nextAll('.ui-multiselect-menu').find('ul li input:checked');
$(".holder").html("");
for (var i = 0; i < checkedOnes.length; i++) {
var lbl = checkedOnes.eq(i).attr('value');
var ctrl = '<input type="checkbox" name="chk" checked="checked" class="chk" id="' + lbl.replace(/[^a-z0-9\s]/gi, '').replace(/[,\s]/g, '') + '">';
$("[id^=id]:checked").each(function () {
$(this).nextAll('.holder:first').append('<div>' + ctrl + lbl + '</div>');
});
}
}
});
});
I'm not entirely sure if I get what you want to do, try this and let me know if it is what you want, here is the fiddle if you want to try it http://jsfiddle.net/8xBcd/
I put the mains in a containing div, that way is easier to make selectors for the diferent mains. check the fiddle please.
<div id="main1-3" >
<input type="checkbox" name="chk1" value="Main1" id="id1" class='checkers'/><label for="Main1"><b>Main1</b></label>
<div class="holder"></div>
</br>
<input type="checkbox" name="chk2" value="Main2" id="id2" class='checkers'><label for="Main2"><b> Main2</b></label>
<div class="holder"></div>
</br>
<input type="checkbox" name="chk3" value="Main3" id="id3" class='checkers'><label for="Main3"><b> Main3</b></label>
<div class="holder"></div>
</div>
<select id="MDCselect" multiple="multiple" class="multiselect">
<option>1</option>
<option>2</option>
<option>3, this space</option>
</select><br>
I've got a function that styles select inputs by generating a div with an anchor, list and a hidden field:
function selectMenu() {
var selectMenu = $("#cf-budget");
$('<input id="' + selectMenu.attr("id") + '-hidden" type="hidden" name="' + selectMenu.attr("name") + '" value="" />').insertAfter(selectMenu);
selectMenu.hide();
var selectTitle = selectMenu.children("option:eq(0)").text();
var newSelectMenu = '<div class="selectmenu"><div class="selectmenu-selected"><a rel="placeholder">'+ selectTitle +'</a></div><ul class="selectmenu-menu"><li><a rel="placeholder">'+ selectTitle +'</a></li>';
selectMenu.find("option:not(:eq(0))").each(function () {
newSelectMenu += '<li><a rel="' + $(this).val() + '">' + $(this).text() + "</a></li>";
});
newSelectMenu += "</ul></div>";
$(newSelectMenu).insertAfter(selectMenu);
var newSelectMenu = $("div.selectmenu");
$("div.selectmenu-selected a", newSelectMenu).live("click", function () {
$("ul.selectmenu-menu", newSelectMenu).toggle();
return false;
});
$("body").live("click", function () {
$("ul.selectmenu-menu", newSelectMenu).hide();
});
$("ul.selectmenu-menu a", newSelectMenu).live("click", function () {
var optionValue = $(this).attr("rel");
var optionText = $(this).text();
$("ul.selectmenu-menu", newSelectMenu).hide();
$("div.selectmenu-selected a", newSelectMenu).text(optionText);
$("#" + selectMenu.attr("id") + "-hidden").val(optionValue);
var activeMessageType = $("ul.message-type.active");
if (activeMessageType.length) {
activeMessageType.slideUp(300, function () {
$("#" + optionValue).addClass("active").slideDown(300);
}).removeClass("active");
} else {
$("#" + optionValue).addClass("active").slideDown(300);
}
return false;
});
}
$(document).ready(function() {
selectMenu();
});
My question is how can I adjust this to make it work for 'x' amount of select inputs? Currently it only takes the Id or class of a single select.
I'm guessing I'd need to pass the function a select id or class name so that it can do it stuff to each dropdown?
I have made a jsFiddle here for this that now is fully working: http://jsfiddle.net/7TaqN/1/
The suggestion by ach was perfect, however there was an issue with the body of your code. The following changes had to be made to make it work:
This line had to be removed as it overrode the 'this' selector:
var selectMenu = $("#cf-budget");
This line had to be modified to select the class with the ID of the element clicked to
prevent all elements from being affected:
$(newSelectMenu).insertAfter(selectMenu);
var newSelectMenu = $("div.selectmenu#"+ selectMenu.attr("id"));
This is the full working code as a jQuery module:
(Note this will only work with jQuery 1.8 as the .live() method you are using is deprecated in 1.9
$.fn.selectMenu = function () {
return this.each(function () {
var selectMenu = $(this);
//Body of your selectMenu() function goes here
//All selectors should be in the context of the selectMenu element
$('<input id="' + selectMenu.attr("id") + '-hidden" type="hidden" name="' + selectMenu.attr("name") + '" value="" />').insertAfter(selectMenu);
selectMenu.hide();
var selectTitle = selectMenu.children("option:eq(0)").text();
var newSelectMenu = '<div id="' + selectMenu.attr("id") + '" class="selectmenu"><div id="' + selectMenu.attr("id") + '" class="selectmenu-selected"><a rel="placeholder">' + selectTitle + '</a></div><ul class="selectmenu-menu"><li><a rel="placeholder">' + selectTitle + '</a></li>';
selectMenu.find("option:not(:eq(0))").each(function () {
newSelectMenu += '<li><a rel="' + $(this).val() + '">' + $(this).text() + "</a></li>";
});
newSelectMenu += "</ul></div>";
$(newSelectMenu).insertAfter(selectMenu);
var newSelectMenu = $("div.selectmenu#"+ selectMenu.attr("id"));
$("div.selectmenu-selected a", newSelectMenu).live("click", function () {
$("ul.selectmenu-menu", newSelectMenu).toggle();
return false;
});
$("body").live("click", function () {
$("ul.selectmenu-menu", newSelectMenu).hide();
});
$("ul.selectmenu-menu a", newSelectMenu).live("click", function () {
var optionValue = $(this).attr("rel");
var optionText = $(this).text();
$("ul.selectmenu-menu", newSelectMenu).hide();
$("div.selectmenu-selected a", newSelectMenu).text(optionText);
$("#" + selectMenu.attr("id") + "-hidden").val(optionValue);
var activeMessageType = $("ul.message-type.active");
if (activeMessageType.length) {
activeMessageType.slideUp(300, function () {
$("#" + optionValue).addClass("active").slideDown(300);
}).removeClass("active");
} else {
$("#" + optionValue).addClass("active").slideDown(300);
}
return false;
});
});
};
$(document).ready(function () {
$('.mySelectClass').selectMenu();
});
You could make it into a jQuery plugin:
$.fn.selectMenu = function() {
return this.each(function() {
var selectMenu = $(this);
//Body of your selectMenu() function goes here
//All selectors should be in the context of the selectMenu element
});
};
Then use it with standard jQuery selectors like so:
$('.mySelectClass').selectMenu();
Edit: Looks like you're already setting the context using the second parameter of jQuery() so additional use of find shouldn't be necessary. That's a lot of code to parse through visually, though -- a jsfiddle might help.
You'll also need to replace some of your selectors so that they're evaluated on the children of the selectMenu element, for example:
selectMenu.find("div.selectmenu-selected a", newSelectMenu).live("click", function () {
I have some code which uses this to allow to keep the same function code but apply it to different form elements which can be seen on a jsFiddle demo
//latest
var maxFields = 10,
currentFields = 1;
$('.form').on('click', '.add', function () {
var value_src = $(this).prev();
var container = $(this).parent().prev();
if ($.trim(value_src.val()) != '') {
if (currentFields < maxFields) {
var value = value_src.val();
var html = '<div class="line">' +
'<input id="accepted" type="text" value="' + value + '" />' +
'<input type="button" value="X" class="remove" />' +
'</div>';
$(html).appendTo(container);
value_src.val('');
currentFields++;
} else {
alert("You tried to add a field when there are already " + maxFields);
}
} else {
alert("You didn't enter anything");
}
})
.on('click', '.remove', function () {
$(this).parents('.line').remove();
currentFields--;
});
My issue is that I still want to be able to limit each section to only have 10 <inputs>, but at the moment each section shares the counter, so 5 in requirements and 5 in qualifications would trigger the 10 limit.
Is there a nice clean way of keeping the input field counter separate for each section?
What you need to do is store the current number of children for each list in a context sensitive way. There are a couple ways you could structure this (it would be easy using MVC libraries or the likes), but the simplest solution for your code will be to just use the DOM. So instead of using your global currentFields variable, instead use container.children().length to get the number of notes in the list you are currently operating on.
http://jsfiddle.net/9sX6X/70/
//latest
var maxFields = 10;
$('.form').on('click', '.add', function () {
var value_src = $(this).prev();
var container = $(this).parent().prev();
if ($.trim(value_src.val()) != '') {
if (container.children().length < maxFields) {
var value = value_src.val();
var html = '<div class="line">' +
'<input id="accepted" type="text" value="' + value + '" />' +
'<input type="button" value="X" class="remove" />' +
'</div>';
$(html).appendTo(container);
value_src.val('');
} else {
alert("You tried to add a field when there are already " + maxFields);
}
} else {
alert("You didn't enter anything");
}
})
.on('click', '.remove', function () {
$(this).parents('.line').remove();
});
You can add a class to each row like form-row
var html = '<div class="line form-row">' +
'<input id="accepted" type="text" value="' + value + '" />' +
'<input type="button" value="X" class="remove" />' +
'</div>';
and count the length by using
console.log($(container).find('.form-row').length);
// Use +1 because initially it is 0
Fiddle http://jsfiddle.net/9sX6X/69/
You can make use of the placeholder property to identify which button triggered the function.
value_src.attr('placeholder');
This string can then be used to access three different counters in an associative array.
Code
var maxFields = 10;
var currentFields = new Object;
$('.form').on('click', '.add', function () {
var value_src = $(this).prev();
var container = $(this).parent().prev();
if ($.trim(value_src.val()) != '') {
var identity = value_src.attr('placeholder');
if(currentFields[identity] == undefined)
currentFields[identity] = 0;
if (currentFields[identity] < maxFields) {
var value = value_src.val();
var html = '<div class="line">' +
'<input id="accepted" type="text" value="' + value + '" />' +
'<input type="button" value="X" class="remove" />' +
'</div>';
$(html).appendTo(container);
value_src.val('');
currentFields[identity]++;
} else {
alert("You tried to add a field when there are already " + maxFields);
}
} else {
alert("You didn't enter anything");
}
})
.on('click', '.remove', function () {
$(this).parents('.line').remove();
currentFields--;
});
JSFiddle: http://jsfiddle.net/9sX6X/73/