jQuery: onchange for select replacement

hankknight
hankknight used Ask the Experts™
on
I use a jQuery plugin to change the appearance of select/option drop downs.

How can I trigger an event when the value is changed?
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head>
<title>Demo</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<style type="text/css">

.jqtSelectWrapper {
	width: 150px;
	position:relative;
	height: 31px;
	background: #F5F5F5 url(http://www.cs.umd.edu/hcil/counterpoint/download/tutorial/down_arrow.gif) no-repeat scroll 99% 4px;
	min-width: 200px;
	margin-right: 17px;
	border: 1px solid #aaa;
	cursor: pointer;
}

.jqtSelectWrapper div span {
	font-size: 12px;
	float: none;
	position: absolute;
	white-space: nowrap;
	height: 31px;
	line-height: 15px;
	padding: 8px 0 0 7px;
	overflow: hidden;
	cursor:pointer;
	width: 194px !important;
}


.jqtSelectWrapper ul {
	position: absolute;
	width: 43px;
	top: 30px;
	left: 0px;
	list-style: none;
	background-color: #FFF;
	border: solid 1px #CCC;
	display: none;
	margin: 0px;
	padding: 0px;
	height: 150px;
	overflow: auto;
	overflow-y: auto;
	z-index:10;
}

.jqtSelectWrapper ul a {
	display: block;
	padding: 5px;
	text-decoration: none;
	color:#333;
	background-color: #FFF;
	font-size: 12px;
}

.jqtSelectWrapper ul a.selected {
	background: #EDEDED;
	color: #333;
}

.jqtSelectWrapper ul a:hover, .jqtSelectWrapper ul a.selected:hover {
	background:#3582c4;
	color: #fff;
}

.jqtHidden {display: none;}

</style>
</head> 
<body> 

<h1>I want to trigger an alert when the value has been changed for either of the items below.</h1>


<h2>This works:</h2>

<select name="s2">
<option value="">---Select---</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
<option value="4">Four</option>
<option value="5">Five</option>
</select>

<h2>This does NOT work:</h2>

<form action="/" method="post"> 
<select name="s1">
<option value="">---Select---</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
<option value="4">Four</option>
<option value="5">Five</option>
</select>
</form>

<h3>The problem is caused by the selection replacement plugin.</h3>

<script type="text/javascript">

(function($){
	var jqtPreloadHoverFocusImg = function(strImgUrl) {
		strImgUrl = strImgUrl.replace(/^url\((.*)\)/,'$1').replace(/^\"(.*)\"$/,'$1');
		var imgHover = new Image();
		imgHover.src = strImgUrl.replace(/\.([a-zA-Z]*)$/,'-hover.$1');
		var imgFocus = new Image();
		imgFocus.src = strImgUrl.replace(/\.([a-zA-Z]*)$/,'-focus.$1');				
	};

	var jqtGetLabel = function(objfield){
	};
	
	/* Hide all open selects */
	var jqtHideSelect = function(oTarget){
	};

	/* Add a new handler for the reset action */
	var jqtReset = function(f){
		var sel;
		$('.jqtSelectWrapper select', f).each(function(){sel = (this.selectedIndex<0) ? 0 : this.selectedIndex; $('ul', $(this).parent()).each(function(){$('a:eq('+ sel +')', this).click();});});
	};


	/***************************
	  Select 
	 ***************************/	
	$.fn.jqTransSelect = function(){
		return this.each(function(index){
			var $select = $(this);

			if($select.hasClass('jqtHidden')) {return;}
			if($select.attr('multiple')) {return;}

			var oLabel  =  jqtGetLabel($select);
			/* First thing we do is Wrap it */
			var $wrapper = $select
				.addClass('jqtHidden')
				.wrap('<div class="jqtSelectWrapper"></div>')
				.parent()
				.css({zIndex: 10-index})
			;
			
			/* Now add the html for the select */
			$wrapper.prepend('<div><span></span><a href="#" class="jqtSelectOpen"></a></div><ul></ul>');
			var $ul = $('ul', $wrapper).css('width',$select.width()).hide();
			/* Now we add the options */
			$('option', this).each(function(i){
				var oLi = $('<li><a href="#" index="'+ i +'">'+ $(this).html() +'</a></li>');
				$ul.append(oLi);
			});
			
			/* Add click handler to the a */
			$ul.find('a').click(function(){
					$('a.selected', $wrapper).removeClass('selected');
					$(this).addClass('selected');	
					/* Fire the onchange event */
					if ($select[0].selectedIndex != $(this).attr('index') && $select[0].onchange) { $select[0].selectedIndex = $(this).attr('index'); $select[0].onchange(); }
					$select[0].selectedIndex = $(this).attr('index');
					$('span:eq(0)', $wrapper).html($(this).html());
					$ul.hide();
					return false;
			});
			/* Set the default */
			$('a:eq('+ this.selectedIndex +')', $ul).click();
			$('span:first', $wrapper).click(function(){$("a.jqtSelectOpen",$wrapper).trigger('click');});
			oLabel && oLabel.click(function(){$("a.jqtSelectOpen",$wrapper).trigger('click');});
			this.oLabel = oLabel;
			
			/* Apply the click handler to the Open */
			var oLinkOpen = $('a.jqtSelectOpen', $wrapper)
				.click(function(){
					//Check if box is already open to still allow toggle, but close all other selects
					if( $ul.css('display') == 'none' ) {jqtHideSelect();} 
					if($select.attr('disabled')){return false;}

					$ul.slideToggle('fast', function(){					
						var offSet = ($('a.selected', $ul).offset().top - $ul.offset().top);
						$ul.animate({scrollTop: offSet});
					});
					return false;
				})
			;

			// Set the new width
			var iSelectWidth = $select.outerWidth();
			var oSpan = $('span:first',$wrapper);
			var newWidth = (iSelectWidth > oSpan.innerWidth())?iSelectWidth+oLinkOpen.outerWidth():$wrapper.width();
			$wrapper.css('width',newWidth);
			$ul.css('width',newWidth-2);
			oSpan.css({width:iSelectWidth});
		
			// Calculate the height if necessary, less elements that the default height
			//show the ul to calculate the block, if ul is not displayed li height value is 0
			$ul.css({display:'block',visibility:'hidden'});
			var iSelectHeight = ($('li',$ul).length)*($('li:first',$ul).height());//+1 else bug ff
			(iSelectHeight < $ul.height()) && $ul.css({height:iSelectHeight,'overflow':'hidden'});//hidden else bug with ff
			$ul.css({display:'none',visibility:'visible'});
			
		});
	};
	$.fn.jqt = function(options){
		
		/* each form */
		 return this.each(function(){
			var selfForm = $(this);
			if(selfForm.hasClass('jqtdone')) {return;}
			selfForm.addClass('jqtdone');
			if( $('select', this).jqTransSelect().length > 0 ){}
			selfForm.bind('reset',function(){var action = function(){jqtReset(this);}; window.setTimeout(action, 10);});			
			
		}); /* End Form each */
				
	};/* End the Plugin */

})(jQuery);

$(function(){$('form').jqt();});

$('select').change(function() {
  alert('Selection has been changed');
});

</script> 
</body>
</html>

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Hi,

there are two points in your script:

1. jQuery uses it's own event-system. So you'll have to check for change instead of onchange  (line 162)

2. $select is a jQuery-object. It's an Array of matched Select-Elements. So $select[0] is a native HtmlSelectElement. Use $select.first() to get the select wrapped by a jQuery-Object

so, buttomline: replace
$select[0].onchange()

Open in new window


by

$select.first().change() 

Open in new window

Author

Commented:
Thanks, dr_Pitter.  I tried your idea but it didn't solve my problem.  Maybe I do not understand how to implement your idea.

Does this also need to be changed?
$('select').change(function() {

Open in new window


Please test the code below and let me know what I am doing wrong, thanks.
no, it doesn't. Just replace line 162 by

if ($select[0].selectedIndex != $(this).attr('index')) { $select[0].selectedIndex = $(this).attr('index'); $select.first().change(); }

Open in new window


by the way:

$select[0].selectedIndex = $(this).attr('index') is redundant, as this statement is in line 162 and 163.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial