Shaye Larsen
asked on
jQuery input elements losing value upon adding item to list
I have implemented a script to be able to add elements to a list and sort them. I can add them fine. I edited the script so that I could edit the elements name after being sent to the list by appending <input> inside the element created in the sort list..
Every time I add a new element to the list all the other input elements in the sort list lose their value.
I got the script from here:
The script here below isjquery.asmselect.js and the doc ready function on my page.
Every time I add a new element to the list all the other input elements in the sort list lose their value.
I got the script from here:
The script here below isjquery.asmselect.js and the doc ready function on my page.
//this is the main script jquery.asmselect.js
/*
* Alternate Select Multiple (asmSelect) 1.0.4 beta - jQuery Plugin
* http://www.ryancramer.com/projects/asmselect/
*
* Copyright (c) 2008 by Ryan Cramer - http://www.ryancramer.com
*
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
*/
(function($) {
$.fn.asmSelect = function(customOptions) {
var options = {
listType: 'ol', // Ordered list 'ol', or unordered list 'ul'
sortable: false, // Should the list be sortable?
highlight: false, // Use the highlight feature?
animate: false, // Animate the the adding/removing of items in the list?
addItemTarget: 'bottom', // Where to place new selected items in list: top or bottom
hideWhenAdded: false, // Hide the option when added to the list? works only in FF
debugMode: false, // Debug mode keeps original select visible
removeLabel: 'remove', // Text used in the "remove" link
highlightAddedLabel: 'Added: ', // Text that precedes highlight of added item
highlightRemovedLabel: 'Removed: ', // Text that precedes highlight of removed item
containerClass: 'asmContainer', // Class for container that wraps this widget
selectClass: 'asmSelect', // Class for the newly created <select>
optionDisabledClass: 'asmOptionDisabled', // Class for items that are already selected / disabled
listClass: 'asmList', // Class for the list ($ol)
listSortableClass: 'asmListSortable', // Another class given to the list when it is sortable
listItemClass: 'asmListItem', // Class for the <li> list items
listItemLabelClass: 'asmListItemLabel', // Class for the label text that appears in list items
inputItemLabelClass: 'asmInputItemLabel', // Class for the label text that appears in list items
removeClass: 'asmListItemRemove', // Class given to the "remove" link
highlightClass: 'asmHighlight', // Class given to the highlight <span>
listPageTypeClass: 'asmPageType' // Class given to page type <span> added by Dale Larsen
};
$.extend(options, customOptions);
return this.each(function(index) {
var $original = $(this); // the original select multiple
var $container; // a container that is wrapped around our widget
var $select; // the new select we have created
var $ol; // the list that we are manipulating
var buildingSelect = false; // is the new select being constructed right now?
var ieClick = false; // in IE, has a click event occurred? ignore if not
var ignoreOriginalChangeEvent = false; // originalChangeEvent bypassed when this is true
function init() {
// initialize the alternate select multiple
// this loop ensures uniqueness, in case of existing asmSelects placed by ajax (1.0.3)
while($("#" + options.containerClass + index).size() > 0) index++;
$select = $("<select></select>")
.addClass(options.selectClass)
.attr('name', options.selectClass + index)
.attr('id', options.selectClass + index);
$selectRemoved = $("<select></select>");
$ol = $("<" + options.listType + "></" + options.listType + ">")
.addClass(options.listClass)
.attr('id', options.listClass + index);
$container = $("<div></div>")
.addClass(options.containerClass)
.attr('id', options.containerClass + index);
buildSelect();
$select.change(selectChangeEvent)
.click(selectClickEvent);
$original.change(originalChangeEvent)
.wrap($container).before($select).before($ol);
if(options.sortable) makeSortable();
if($.browser.msie) $ol.css('display', 'inline-block');
}
function makeSortable() {
// make any items in the selected list sortable
// requires jQuery UI sortables, draggables, droppables
$ol.sortable({
items: 'li.' + options.listItemClass,
handle: '.' + options.listItemLabelClass,
axis: 'y',
update: function(e, data) {
var updatedOptionId;
$(this).children("li").each(function(n) {
$option = $('#' + $(this).attr('rel'));
if($(this).is(".ui-sortable-helper")) {
updatedOptionId = $option.attr('id');
return;
}
$original.append($option);
});
if(updatedOptionId) triggerOriginalChange(updatedOptionId, 'sort');
}
}).addClass(options.listSortableClass);
}
function selectChangeEvent(e) {
// an item has been selected on the regular select we created
// check to make sure it's not an IE screwup, and add it to the list
if($.browser.msie && $.browser.version < 7 && !ieClick) return;
var id = $(this).children("option:selected").slice(0,1).attr('rel');
addListItem(id);
ieClick = false;
triggerOriginalChange(id, 'add'); // for use by user-defined callbacks
}
function selectClickEvent() {
// IE6 lets you scroll around in a select without it being pulled down
// making sure a click preceded the change() event reduces the chance
// if unintended items being added. there may be a better solution?
ieClick = true;
}
function originalChangeEvent(e) {
// select or option change event manually triggered
// on the original <select multiple>, so rebuild ours
if(ignoreOriginalChangeEvent) {
ignoreOriginalChangeEvent = false;
return;
}
$select.empty();
$ol.empty();
buildSelect();
// opera has an issue where it needs a force redraw, otherwise
// the items won't appear until something else forces a redraw
if($.browser.opera) $ol.hide().fadeIn("fast");
}
function buildSelect() {
// build or rebuild the new select that the user
// will select items from
buildingSelect = true;
// add a first option to be the home option / default selectLabel
$select.prepend("<option>" + $original.attr('title') + "</option>");
$original.children("option").each(function(n) {
var $t = $(this);
var id;
if(!$t.attr('id')) $t.attr('id', 'asm' + index + 'option' + n);
id = $t.attr('id');
if($t.is(":selected")) {
addListItem(id);
addSelectOption(id, true);
} else {
addSelectOption(id);
}
});
if(!options.debugMode) $original.hide(); // IE6 requires this on every buildSelect()
selectFirstItem();
buildingSelect = false;
}
function addSelectOption(optionId, disabled) {
// add an <option> to the <select>
// used only by buildSelect()
if(disabled == undefined) var disabled = false;
var $O = $('#' + optionId);
var $option = $("<option>" + $O.text() + "</option>")
.val($O.val())
.attr('rel', optionId);
if(disabled) disableSelectOption($option);
$select.append($option);
}
function selectFirstItem() {
// select the firm item from the regular select that we created
$select.children(":eq(0)").attr("selected", true);
}
function disableSelectOption($option) {
// make an option disabled, indicating that it's already been selected
// because safari is the only browser that makes disabled items look 'disabled'
// we apply a class that reproduces the disabled look in other browsers
$option.addClass(options.optionDisabledClass)
.attr("selected", false)
.attr("disabled", true);
if(options.hideWhenAdded) $option.hide();
if($.browser.msie) $select.hide().show(); // this forces IE to update display
}
function enableSelectOption($option) {
// given an already disabled select option, enable it
$option.removeClass(options.optionDisabledClass)
.attr("disabled", false);
if(options.hideWhenAdded) $option.show();
if($.browser.msie) $select.hide().show(); // this forces IE to update display
}
function addListItem(optionId) {
// add a new item to the html list
var $O = $('#' + optionId);
if(!$O) return; // this is the first item, selectLabel
var $removeLink = $("<a></a>")
.attr("href", "#")
.addClass(options.removeClass)
.prepend(options.removeLabel)
.click(function() {
dropListItem($(this).parent('li').attr('rel'));
return false;
});
var $itemInput = $('<input type="text"/>')
.addClass(options.inputItemLabelClass)
.val("");
var $itemLabel = $('<span></span>')
.append($itemInput)
.addClass(options.listItemLabelClass);
var $itemPageType = $('<span></span>')
.addClass(options.listPageTypeClass)
.html($O.html());
var $item = $("<li></li>")
.attr('rel', optionId)
.addClass(options.listItemClass)
.append($itemLabel)
.append($itemPageType)
.append($removeLink)
.hide();
if(!buildingSelect) {
if($O.is(":selected")) return; // already have it
$O.attr('selected', true);
}
if(options.addItemTarget == 'top' && !buildingSelect) {
$ol.prepend($item);
if(options.sortable) $original.prepend($O);
} else {
$ol.append($item);
if(options.sortable) $original.append($O);
}
addListItemShow($item);
disableSelectOption($("[rel=" + optionId + "]", $select));
if(!buildingSelect) {
setHighlight($item, options.highlightAddedLabel);
selectFirstItem();
if(options.sortable) $ol.sortable("refresh");
}
}
function addListItemShow($item) {
// reveal the currently hidden item with optional animation
// used only by addListItem()
if(options.animate && !buildingSelect) {
$item.animate({
opacity: "show",
height: "show"
}, 150, "swing", function() { //default 100
$item.animate({
height: "+=2px"
}, 100, "swing", function() {//default 50
$item.animate({
height: "-=2px"
}, 95, "swing");//default 25
});
});
} else {
$item.show();
}
}
function dropListItem(optionId, highlightItem) {
// remove an item from the html list
if(highlightItem == undefined) var highlightItem = true;
var $O = $('#' + optionId);
$O.attr('selected', false);
$item = $ol.children("li[rel=" + optionId + "]");
dropListItemHide($item);
enableSelectOption($("[rel=" + optionId + "]", options.removeWhenAdded ? $selectRemoved : $select));
if(highlightItem) setHighlight($item, options.highlightRemovedLabel);
triggerOriginalChange(optionId, 'drop');
}
function dropListItemHide($item) {
// remove the currently visible item with optional animation
// used only by dropListItem()
if(options.animate && !buildingSelect) {
$prevItem = $item.prev("li");
$item.animate({
opacity: "hide",
height: "hide"
}, 120, "linear", function() {//default 100
$prevItem.animate({
height: "-=2px"
}, 70, "swing", function() {//default 50
$prevItem.animate({
height: "+=2px"
}, 120, "swing"); //default 100
});
$item.remove();
});
} else {
$item.remove();
}
}
function setHighlight($item, label) {
// set the contents of the highlight area that appears
// directly after the <select> single
// fade it in quickly, then fade it out
if(!options.highlight) return;
$select.next("#" + options.highlightClass + index).remove();
var $highlight = $("<span></span>")
.hide()
.addClass(options.highlightClass)
.attr('id', options.highlightClass + index)
.html(label + $item.children("." + options.listItemLabelClass).slice(0,1).text());
$select.after($highlight);
$highlight.fadeIn(200, function() {//defalut "fast"
setTimeout(function() { $highlight.fadeOut("slow"); }, 100);//default 50
});
}
function triggerOriginalChange(optionId, type) {
// trigger a change event on the original select multiple
// so that other scripts can pick them up
ignoreOriginalChangeEvent = true;
$option = $("#" + optionId);
$original.trigger('change', [{
'option': $option,
'value': $option.val(),
'id': optionId,
'item': $ol.children("[rel=" + optionId + "]"),
'type': type
}]);
}
init();
});
};
})(jQuery);
//this is the doc ready function that goes on my page.
$(document).ready(function() {
$("div[multiple]").asmSelect({
addItemTarget: 'bottom',
animate: true,
removeLabel: 'X',
highlight: false,
sortable: true
});
$("#add_blank_btn").click(function() {
var addBlank = $("#add_blank").val();
var $option = $("<option></option>").text(addBlank).attr("selected", true);
$("#pages").append($option).change();
return false;
});
$("#add_about_btn").click(function() {
var addAbout = $("#add_about").val();
var $option = $("<option></option>").text(addAbout).attr("selected", true);
$("#pages").append($option).change();
return false;
});
$("#add_articles_btn").click(function() {
var addArticles = $("#add_articles").val();
var $option = $("<option></option>").text(addArticles).attr("selected", true);
$("#pages").append($option).change();
return false;
});
$("#add_calendar_btn").click(function() {
var addCalendar = $("#add_calendar, #add_contact, #add_hours, #add_jobs, #add_news, #add_press, #add_support").val();
var $option = $("<option></option>").text(addCalendar).attr("selected", true);
$("#pages").append($option).change();
return false;
});
$("#add_contact_btn").click(function() {
var addContact = $("#add_contact").val();
var $option = $("<option></option>").text(addContact).attr("selected", true);
$("#pages").append($option).change();
return false;
});
$("#add_faq_btn").click(function() {
var addFaq = $("#add_faq").val();
var $option = $("<option></option>").text(addFaq).attr("selected", true);
$("#pages").append($option).change();
return false;
});
$("#add_hours_btn").click(function() {
var addHours = $("#add_hours").val();
var $option = $("<option></option>").text(addHours).attr("selected", true);
$("#pages").append($option).change();
return false;
});
$("#add_jobs_btn").click(function() {
var addJobs = $("#add_jobs").val();
var $option = $("<option></option>").text(addJobs).attr("selected", true);
$("#pages").append($option).change();
return false;
});
$("#add_news_btn").click(function() {
var addNews = $("#add_news").val();
var $option = $("<option></option>").text(addNews).attr("selected", true);
$("#pages").append($option).change();
return false;
});
$("#add_press_btn").click(function() {
var addPress = $("#add_press").val();
var $option = $("<option></option>").text(addPress).attr("selected", true);
$("#pages").append($option).change();
return false;
});
$("#add_support_btn").click(function() {
var addSupport = $("#add_support").val();
var $option = $("<option></option>").text(addSupport).attr("selected", true);
$("#pages").append($option).change();
return false;
});
});
ASKER
Thanks for the reply.
Sorry, that was a test I was doing to try and fix this. I now removed that line, it still has the same problem.
Sorry, that was a test I was doing to try and fix this. I now removed that line, it still has the same problem.
what about removing
.html($O.html());
?:]
.html($O.html());
?:]
ASKER
thanks, but still not working with that change...
ASKER
I think that the element is being refreshed or something when I append a new element to the list, or I could be wrong.
Is there a way to hold an elements value so that it is no lost, or a way that when someone appends a new element to the list it take the values of the inputs and reassigns them?
Is there a way to hold an elements value so that it is no lost, or a way that when someone appends a new element to the list it take the values of the inputs and reassigns them?
well yes you could save that value, but if values beeing removed after adding new one.. then it means that they are all removed and added again. And this should not be like this... hmm... we could also store values but this is a bad idea (like hacking instead of good programming)
ASKER
Yeah, I prefer to avoid hacking.
Can you give me some example page on web with code running ? That would help me debug it ;)
ASKER
Look at function buildSelect - as there in comments it just builds or rebuilds whole select element.
You just need to:
Put there (exacly in addListItem (optionId)) a proper value that will be stored before removing every elements in this list.
Removing elements is here:
function originalChangeEvent(e) {
...
$select.empty();
$ol.empty();
buildSelect();
Is this enough here for you ?
You just need to:
Put there (exacly in addListItem (optionId)) a proper value that will be stored before removing every elements in this list.
Removing elements is here:
function originalChangeEvent(e) {
...
$select.empty();
$ol.empty();
buildSelect();
Is this enough here for you ?
ASKER
Thank you so much, but I am afraid I'm not sure what to add or delete? I'll keep looking into it but I'm a bit confused.
originalChangeEvent is a function that is fired when you trying to add new input. It just removes all inputs that you had before and create a whole new list (buildSelect function do that using an addListItem function). So what you can do is to store input values in originalChangeEvent just before removing elements and then use this value to fill proper data inside addListItem function. Is that sount clear ? Or still have problem ?:)
ASKER
Thanks, Sounds clear, I'm just not that advanced with javascript...
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Wow, thanks. I have implemented those changes. Now the appended element has no input field and I don't see why. I have tested it through it seems all the elements are there to create it.
When I remove:
.value = $O.attr("last");
From:
var $itemInput = $('<input type="text"/>')
.addClass(options.inputIte mLabelClas s)
.value = $O.attr("last");
The input fields show again but, of course, still without the desired functionality.
The updates have been made to the test page:
http://dalelarsen.com/fab/sort.php
When I remove:
.value = $O.attr("last");
From:
var $itemInput = $('<input type="text"/>')
.addClass(options.inputIte
.value = $O.attr("last");
The input fields show again but, of course, still without the desired functionality.
The updates have been made to the test page:
http://dalelarsen.com/fab/sort.php
sorry Mine mistake
should be
var $itemInput = $('<input type="text"/>').addClass(o ptions.inp utItemLabe lClass).at tr("value" ,$O.attr(" last"));
should be
var $itemInput = $('<input type="text"/>').addClass(o
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Perfect thanks!!!
ASKER
Wilq, I need help at the following question that relates to this one. I need to do the same thing but detect if the radio was checked or not.
https://www.experts-exchange.com/questions/24574082/jQuery-sort-losing-if-radio-is-checked-or-not.html
https://www.experts-exchange.com/questions/24574082/jQuery-sort-losing-if-radio-is-checked-or-not.html
.addClass(options.inputIte
.val("");
you have .val("") ?? What for ? can you remove it ?