Solved

jQuery input elements losing value upon adding item to list

Posted on 2009-05-19
19
1,551 Views
Last Modified: 2012-05-07
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.
//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;
	});
	
});

Open in new window

0
Comment
Question by:Shaye Larsen
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 10
  • 9
19 Comments
 
LVL 18

Expert Comment

by:Pawel Witkowski
ID: 24430950
line 260:                        var $itemInput = $('<input type="text"/>')
                              .addClass(options.inputItemLabelClass)
                              .val("");



you have .val("")   ?? What for ? can you remove it ?



0
 
LVL 1

Author Comment

by:Shaye Larsen
ID: 24432955
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.
0
 
LVL 18

Expert Comment

by:Pawel Witkowski
ID: 24440718
what about removing


.html($O.html());

?:]
0
Creating Instructional Tutorials  

For Any Use & On Any Platform

Contextual Guidance at the moment of need helps your employees/users adopt software o& achieve even the most complex tasks instantly. Boost knowledge retention, software adoption & employee engagement with easy solution.

 
LVL 1

Author Comment

by:Shaye Larsen
ID: 24442447
thanks, but still not working with that change...
0
 
LVL 1

Author Comment

by:Shaye Larsen
ID: 24454201
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?
0
 
LVL 18

Expert Comment

by:Pawel Witkowski
ID: 24457269
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)
0
 
LVL 1

Author Comment

by:Shaye Larsen
ID: 24458301
Yeah, I prefer to avoid hacking.
0
 
LVL 18

Expert Comment

by:Pawel Witkowski
ID: 24464824
Can you give me some example page on web with code running ? That would help me debug it ;)
0
 
LVL 1

Author Comment

by:Shaye Larsen
ID: 24467627
Alright, I have made this test page.

Go to:
http://dalelarsen.com/fab/sort.php
0
 
LVL 18

Expert Comment

by:Pawel Witkowski
ID: 24468413
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 ?
0
 
LVL 1

Author Comment

by:Shaye Larsen
ID: 24468517
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.
0
 
LVL 18

Expert Comment

by:Pawel Witkowski
ID: 24468555
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 ?:)
0
 
LVL 1

Author Comment

by:Shaye Larsen
ID: 24468586
Thanks, Sounds clear, I'm just not that advanced with javascript...
0
 
LVL 18

Accepted Solution

by:
Pawel Witkowski earned 500 total points
ID: 24469073
Before $select.empty()  do:


$("#asmList0 li").each(function()
{
var value=($("input",this).attr("value"));

$("#"+this.getAttribute('rel')).attr("last",value);
});



then in addListItem do that:

change this:

 var $itemInput = $('<input type="text"/>').addClass(options.inputItemLabelClass);



to:


 var $itemInput = $('<input type="text"/>').addClass(options.inputItemLabelClass).value = $O.attr("last");
0
 
LVL 1

Author Comment

by:Shaye Larsen
ID: 24469261
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.inputItemLabelClass)
.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 
0
 
LVL 18

Expert Comment

by:Pawel Witkowski
ID: 24469336
sorry Mine mistake

should be

var $itemInput = $('<input type="text"/>').addClass(options.inputItemLabelClass).attr("value",$O.attr("last"));
0
 
LVL 18

Assisted Solution

by:Pawel Witkowski
Pawel Witkowski earned 500 total points
ID: 24469345
Or a

var $itemInput = $('<input type="text"/>').addClass(options.inputItemLabelClass);
$itemInput.attr("value",$O.attr("last"));

if still got problem
0
 
LVL 1

Author Closing Comment

by:Shaye Larsen
ID: 31583298
Perfect thanks!!!
0
 
LVL 1

Author Comment

by:Shaye Larsen
ID: 24880844
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.

http://www.experts-exchange.com/Programming/Languages/Scripting/JavaScript/Jquery/Q_24574082.html
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

FAQ pages provide a simple way for you to supply and for customers to find answers to the most common questions about your company. Here are six reasons why your company website should have a FAQ page
Australian government abolished Visa 457 earlier this April and this article describes how this decision might affect Australian IT scene and IT experts.
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn how to count occurrences of each item in an array.

734 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question