Skip to content

Instantly share code, notes, and snippets.

@arunpjohny
Last active December 14, 2015 15:18
Show Gist options
  • Save arunpjohny/5106441 to your computer and use it in GitHub Desktop.
Save arunpjohny/5106441 to your computer and use it in GitHub Desktop.
/*
* jQuery Related Selects plug-in 1.1
*
* http://www.erichynds.com/jquery/jquery-related-dependent-selects-plugin/
* http://github.com/ehynds/jquery-related-selects
*
* Copyright (c) 2009 Eric Hynds
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*/
(function($){
$.fn.relatedSelects = function(opts){
opts = $.extend({}, $.fn.relatedSelects.defaults, opts);
return this.each(function(){
new RelatedSelect(this, opts);
});
};
var RelatedSelect = function(context, opts) {
var $context = $(context), selects = [];
// if the selects option is an array convert it to an object
if($.isArray(opts.selects)){
selectsToObj();
}
// make array of select names
$.each(opts.selects, function(key){
selects.push(key);
});
// cache the options where the value is empty for each select before processing occurs.
saveDefaultOptionText();
// go through each select box & settings passed into options
$.each(opts.selects, function(elem,o){
var $select = $context.find("select[name='" + elem + "']"), // jquery ref to this select box
$next = next(elem), // the select box after this one
selectedValue = $select.val(); // currently selected value
// extend element-specific options
// set the defaultOptionText to whatever was passed in or the option where value is blank.
o = $.extend({
defaultOptionText: opts.defaultOptionText || $select.data('defaultOption')
}, opts, o);
// store the new default option text
$select.data('defaultOption', o.defaultOptionText);
// bind the change event
$select.change(function(){
o.onChange.call($select);
process( $select, $next, elem, o );
});
// if there is already a selected option in this select and the next one is already populated, skip this iteration
if(selectedValue && selectedValue.length > 0 && isPopulated($next)){
return;
}
// process the select box upon page load
process( $select, $next, elem, o );
});
function saveDefaultOptionText(){
var $select, text;
for(var x=1, len=selects.length; x<len; x++){
$select = $context.find("select[name='"+ selects[x] +"']");
text = $select.find("option[value='']").text();
$select.data('defaultOption', text);
}
}
function process($select,$next,elem,o){
if(!$next.length){
return;
}
var value = $.trim($select.val());
// if this select box's length has been changed to a legit value, and there is another select box after this one
if(value.length > 0 && value !== o.loadingMessage && $next){
// reset all selects after this one
resetAfter(elem);
// populate the next select
populate($select,$next,o);
// otherwise, make all the selects after this one disabled and select the first option
} else if($next){
resetAfter(elem);
}
}
function populate($caller,$select,o){
var selectors = [], params;
// build a selector for each select box in this context
for(var x=0, len=selects.length; x<len; x++){
selectors.push('select[name="'+selects[x]+'"]');
}
// take those selectors and serialize the data in them
params = $( selectors.join(','), $context ).serialize();
// disable this select box, add loading msg
$select.attr('disabled', 'disabled').html('<option value="">' + o.loadingMessage + '</option>');
console.log('ajax')
// perform ajax request
$.ajax({
beforeSend: function(){
console.log('brefore',arguments)
return o.onLoadingStart.apply($select, Array.prototype.slice.call(arguments,0));
},
complete: function(){ o.onLoadingEnd.call($select); },
dataType: o.dataType,
data: params,
url: o.onChangeLoad,
success: function(data){
var html = [], defaultOptionText = $select.data('defaultOption');
// set the default option in the select.
if(defaultOptionText.length > 0){
html.push('<option value="" selected="selected">' + defaultOptionText + '</option>');
}
// if the value returned from the ajax request is valid json and isn't empty
if(o.dataType === 'json' && typeof data === 'object' && data){
// build the options
$.each(data, function(i,item){
html.push('<option value="'+i+'">' + item + '</option>');
});
$select.html( html.join('') ).removeAttr('disabled');
// html datatype
} else if(o.dataType === 'html' && $.trim(data).length > 0){
html.push($.trim(data));
$select.html( html.join('') ).removeAttr('disabled');
// if the response is invalid/empty, reset the default option and fire the onEmptyResult callback
} else {
$select.html( html.join('') );
if(!o.disableIfEmpty){ $select.removeAttr('disabled'); }
o.onEmptyResult.call($caller);
}
}
});
}
function isPopulated($select){
var options = $select.find('option');
return (options.length === 0 || (options.length === 1 && options.filter(':first').attr('value').length === 0)) ? false : true;
}
function resetAfter(elem){
var thispos = getPosition(elem);
for (var x=thispos+1, len=selects.length; x<len; x++){
$("select[name='" + selects[x] + "']", $context ).attr('disabled','disabled').find('option:first').attr('selected','selected');
}
}
function next(elem){
return $context.find("select[name='" + selects[ getPosition(elem)+1 ] + "']");
}
// returns the position of an element in the array
function getPosition(elem){
for (var i=0, len=selects.length; i<len; i++){
if(selects[i] === elem){
return i;
}
}
}
// converts an array of selects to an object
function selectsToObj(){
var arrSelects = opts.selects;
opts.selects = {};
for(var i=0, len=arrSelects.length; i<len; i++){
opts.selects[ arrSelects[i] ] = {};
}
}
};
$.fn.relatedSelects.defaults = {
selects: {},
loadingMessage: 'Loading, please wait...',
disableIfEmpty: false,
dataType: 'json',
onChangeLoad: '',
onLoadingStart: function(){},
onLoadingEnd: function(){},
onChange: function(){},
onEmptyResult: function(){}
};
})(jQuery);
/*
* jQuery Related Selects plug-in 1.1
*
* http://www.erichynds.com/jquery/jquery-related-dependent-selects-plugin/
* http://github.com/ehynds/jquery-related-selects
*
* Copyright (c) 2009 Eric Hynds
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*/
(function($){
$.fn.relatedSelects = function(opts){
opts = $.extend({}, $.fn.relatedSelects.defaults, opts);
return this.each(function(){
new RelatedSelect(this, opts);
});
};
var RelatedSelect = function(context, opts) {
var $context = $(context), selects = [];
// if the selects option is an array convert it to an object
if($.isArray(opts.selects)){
selectsToObj();
}
// make array of select names
$.each(opts.selects, function(){
selects.push(key);
});
// cache the options where the value is empty for each select before processing occurs.
saveDefaultOptionText();
// go through each select box & settings passed into options
$.each(opts.selects, function(elem,o){
var $select = $context.find("select[name='" + elem + "']"), // jquery ref to this select box
$next = next(elem), // the select box after this one
selectedValue = $select.val(); // currently selected value
// extend element-specific options
// set the defaultOptionText to whatever was passed in or the option where value is blank.
o = $.extend({
defaultOptionText: opts.defaultOptionText || $select.data('defaultOption')
}, opts, o);
// store the new default option text
$select.data('defaultOption', o.defaultOptionText);
// bind the change event
$select.change(function(){
o.onChange.call($select);
process( $select, $next, elem, o );
});
// if there is already a selected option in this select and the next one is already populated, skip this iteration
if(selectedValue && selectedValue.length > 0 && isPopulated($next)){
return;
}
// process the select box upon page load
process( $select, $next, elem, o );
});
function saveDefaultOptionText(){
var $select, text;
for(var x=1, len=selects.length; x<len; x++){
$select = $context.find("select[name='"+ selects[x] +"']");
text = $select.find("option[value='']").text();
$select.data('defaultOption', text);
}
}
function process($select,$next,elem,o){
if(!$next.length){
return;
}
var value = $.trim($select.val());
// if this select box's length has been changed to a legit value, and there is another select box after this one
if(value.length > 0 && value !== o.loadingMessage && $next){
// reset all selects after this one
resetAfter(elem);
// populate the next select
populate($select,$next,o);
// otherwise, make all the selects after this one disabled and select the first option
} else if($next){
resetAfter(elem);
}
}
function populate($caller,$select,o){
var selectors = [], params;
// build a selector for each select box in this context
for(var x=0, len=selects.length; x<len; x++){
selectors.push('select[name="'+selects[x]+'"]');
}
// take those selectors and serialize the data in them
params = $( selectors.join(','), $context ).serialize();
// disable this select box, add loading msg
$select.attr('disabled', 'disabled').html('<option value="">' + o.loadingMessage + '</option>');
// perform ajax request
$.ajax({
beforeSend: function(){ o.onLoadingStart.call($select); },
complete: function(){ o.onLoadingEnd.call($select); },
dataType: o.dataType,
data: params,
url: o.onChangeLoad,
success: function(data){
var html = [], defaultOptionText = $select.data('defaultOption');
// set the default option in the select.
if(defaultOptionText.length > 0){
html.push('<option value="" selected="selected">' + defaultOptionText + '</option>');
}
// if the value returned from the ajax request is valid json and isn't empty
if(o.dataType === 'json' && typeof data === 'object' && data){
// build the options
$.each(data, function(i,item){
html.push('<option value="'+i+'">' + item + '</option>');
});
$select.html( html.join('') ).removeAttr('disabled');
// html datatype
} else if(o.dataType === 'html' && $.trim(data).length > 0){
html.push($.trim(data));
$select.html( html.join('') ).removeAttr('disabled');
// if the response is invalid/empty, reset the default option and fire the onEmptyResult callback
} else {
$select.html( html.join('') );
if(!o.disableIfEmpty){ $select.removeAttr('disabled'); }
o.onEmptyResult.call($caller);
}
}
});
}
function isPopulated($select){
var options = $select.find('option');
return (options.length === 0 || (options.length === 1 && options.filter(':first').attr('value').length === 0)) ? false : true;
}
function resetAfter(elem){
var thispos = getPosition(elem);
for (var x=thispos+1, len=selects.length; x<len; x++){
$("select[name='" + selects[x] + "']", $context ).attr('disabled','disabled').find('option:first').attr('selected','selected');
}
}
function next(elem){
return $context.find("select[name='" + selects[ getPosition(elem)+1 ] + "']");
}
// returns the position of an element in the array
function getPosition(elem){
for (var i=0, len=selects.length; i<len; i++){
if(selects[i] === elem){
return i;
}
}
}
// converts an array of selects to an object
function selectsToObj(){
var arrSelects = opts.selects;
opts.selects = {};
for(var i=0, len=arrSelects.length; i<len; i++){
opts.selects[ arrSelects[i] ] = {};
}
}
};
$.fn.relatedSelects.defaults = {
selects: {},
loadingMessage: 'Loading, please wait...',
disableIfEmpty: false,
dataType: 'json',
onChangeLoad: '',
onLoadingStart: function(){},
onLoadingEnd: function(){},
onChange: function(){},
onEmptyResult: function(){}
};
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment