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 () {
Related
I've a form when I click one radio button to load a subform.
Ok this work perfectly, but has 3 selectors that I need external data when only this subform loaded.
So, I did in this way:
$(document).on('focus', '#reemb', function () {
$.getJSON("/banks.php", function (json) {
$('#bank').empty();
$.each(json, function (i, obj) {
$('#bank').append($('<option>').text(obj.name).attr('value', obj.code));
});
});
$.getJSON('/statecity.json', function (data) {
var items = [];
var options = '<option value="">State</option>';
$.each(data, function (key, val) {
options += '<option value="' + val.name + '">' + val.name + '</option>';
});
$("#state").html(options);
$("#state").change(function () {
var options_city = '';
var str = "";
$("#state option:selected").each(function () {
str += $(this).text();
});
$.each(data, function (key, val) {
if (val.name == str) {
$.each(val.city, function (key_city, val_city) {
options_city += '<option value="' + val_city + '">' + val_city + '</option>';
});
}
});
$("#city ").html(options_city);
}).change();
});
});
This work fine, but everytime that I need to change one date the selectors clear and load again.
I tried to add tag onload to start the function to load selectors in this subform, but don't works. Also tried change events to .on, but also don't work.
How I need to do this?
Thx!!
Not knowing what #reemb is, I would empty the relevant sub selects:
If the container holding the selects is ALSO emptied, you need to delegate all even handlers of objects inside too - like $(document).on("change","#bank", function() {
$(document).on('click', '#reemb', function() {
$.getJSON("/banks.php", function(json) {
$('#bank').empty();
$.each(json, function(i, obj) {
$('#bank').append($('<option>').text(obj.name).attr('value', obj.code)).change();
});
});
$('#bank').on("change", function() {
$('#city').empty();
$.getJSON('/statecity.json', function(data) {
var items = [];
var options = '<option value="">State</option>';
$.each(data, function(key, val) {
options += '<option value="' + val.name + '">' + val.name + '</option>';
});
$("#state").html(options).change(); // if needed
});
$("#state").on("change", function() {
var options_city = '';
var str = "";
$("#state option:selected").each(function() {
str += $(this).text();
});
$.each(data, function(key, val) {
if (val.name == str) {
$.each(val.city, function(key_city, val_city) {
options_city += '<option value="' + val_city + '">' + val_city + '</option>';
});
}
});
$("#city ").html(options_city).change(); // if needed
});
});
});
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 trying to make a website using jquery-1.11.1 where I want a <textarea> to be spawned whenever I click on the link which only shows on mouseenter on a div. But I'm getting an error in my console,
Uncaught ReferenceError: inputdivEditor is not defined (Please ignore JSFiddle errors)
I've absolutely no idea why I'm getting this. Here are my codes,
$(document).ready(function () {
$("[id^=divEditor-]").each(function () {
var content = $(this).html();
var targetID = $(this).attr('id');
var txtID = 'input' + targetID;
$('<textarea id="input' + targetID + '" name="' + txtID + '" >' + content + '</textarea>').insertBefore(this).css('display', 'none');
var button = "<a onclick='activateDivEditor(this, " + txtID + ")' class='custom-edit-button editDiv' id='active" + targetID + "'>Embed Code</a>";
$(this).on('mouseenter', function () {
$(this).prepend($(button));
$(this).css('position', 'relative');
});
$(this).on('mouseleave', function () {
$('.editDiv').remove();
});
});
});
function activateDivEditor(btn, txtId) {
var targetID = $(btn).parent().get(0).id;
var update = "<a onclick='deactivateDivEditor(this, " + txtId + ")' class='custom-edit-button updatediv' id='deactive" + targetID + "'>Update</a>";
var cancel = "<a onclick='cancelactivateDivEditor(this)' class='custom-edit-button cancel' id='cancelactive" + targetID + "'>Cancel</a>";
var targetClass = $('#' + targetID).attr('class');
var targetWidth = $('#' + targetID).width();
$('#' + targetID).css('display', 'none');
$('#input' + targetID).css('display', 'block').css('width', targetWidth - 2).css('height', '125px');
$('#input' + targetID).parent().css('position', 'relative');
$(update).prependTo($('#input' + targetID).parent());
$(cancel).prependTo($('#input' + targetID).parent());
}
JSFiddle Demo
How can I generate a textarea whenever I click on the button link? Need this help badly. Thanks.
Can I use $(this).parentsUntil()... after a $.post?
I need to remember what select element from the DOM changed and then append the information collected from my PHP to next select.
//OPTION SELECTED
$('body').on('change','.provincias, .partidos', function(e) {
var idSelect = $(this).attr('id');
var dataSelect = $(this).select2('data');
var value = dataSelect.id;
$.post('php/select/script.php', {id:idSelect, id_provincia:value, id_partido:value } , function(respuesta) {
data = JSON.parse(respuesta);
if(data.control == 0){
alert(data.error)
window.location.replace(data.url);
}else{
if(idSelect == data.thisSelect){
for(var u=0; u<data.array1.length; u++){
$(this).parentsUntil('.formRow').next().children(data.nextSelect).append('<option value="' + data.array1[u].id + '">' + data.array1[u].nombre + '</option>');
}
}else if(idSelect == data.thisSelect){
for(var t=0; t<data.array1.length; t++){
$(this).parentsUntil('.formRow').next().children('".' + data.nextSelect +'."').append('<option value="' + data.array1[u].id + '">' + data.array1[u].nombre + '</option>');
}
}
}
});
});
The typical solution is to define another variable to hold the value of this, e.g. self, or in this case, you might want to call it target:
...
var target = this;
$.post('php/select/script.php', {id:idSelect, id_provincia:value, id_partido:value } , function(respuesta) {
// Use target here.
}
just save the $(this) in a variable.
$('body').on('change','.provincias, .partidos', function(e) {
var el = $(this);
...
el.parentsUntil('.formRow').next().children(data.nextSelect).append('<option value="' + data.array1[u].id + '">' + data.array1[u].nombre + '</option>');
After replacign the location with new parameters, the page after loaded doesn't get the paramaters value, despite there are values in the parameters
the used code is :
function getURLParameter(name) {
return
decodeURI((RegExp(name + '=' + '(.+?)(&|$)').exec(location.search) || [, null])[1]);
}
$(document).ready(function () {
$(".sub").slideUp();
var div = getURLParameter("div");
var ddl = getURLParameter("ddl");
alert(div);
// alert("ManageTrainingNeeds.aspx?div=" + div + "&ddl=" + ddl);
// $("#" + div).slideDown();
// $("#ddlObjectiveGroup").val("'" + ddl + "'");
});
$(".btnAddSub").live("click", function () {
var diva = $(this).parent().parent().parent().parent().parent().parent().attr("id");
var ddl = $("#ddlObjectiveGroup option:selected").val();
window.location.replace("ManageTrainingNeeds.aspx?div=" + diva + "&ddl=" + ddl);
});
this alert(div); return undefined.. despite the div vairable in click event has a value
Try encoding the parameters and also canceling the default action in the click event:
function getURLParameter(name) {
return decodeURIComponent((RegExp(name + '=' + '(.+?)(&|$)').exec(location.search) || [, null])[1]);
}
$(document).ready(function () {
var div = getURLParameter('div');
var ddl = getURLParameter('ddl');
alert(div + ' ' + ddl);
});
$('.btnAddSub').live('click', function () {
var diva = encodeURIComponent($(this).parent().parent().parent().parent().parent().parent().attr('id'));
var ddl = encodeURIComponent($('#ddlObjectiveGroup').val());
window.location.replace('/ManageTrainingNeeds.aspx?div=' + diva + '&ddl=' + ddl);
return false;
});
Instead of fiddling with the URLs yourself, you could use a library for the job - such as URI.js. (sorry for the self-promo)
$(document).ready(function () {
var search = URI().search(true);
alert(search.div + ' ' + search.ddl);
});
$('.btnAddSub').live('click', function (e) {
var uri = URI('/ManageTrainingNeeds.aspx');
uri.search({
diva: $(this).parent().parent().parent().parent().parent().parent().attr('id'),
ddl: $('#ddlObjectiveGroup').val()
});
window.location.href = uri.toString();
e.preventDefault();
});