Skip to content

Instantly share code, notes, and snippets.

@datfaf
Created July 27, 2011 16:19
Show Gist options
  • Save datfaf/1109724 to your computer and use it in GitHub Desktop.
Save datfaf/1109724 to your computer and use it in GitHub Desktop.
js dynamic_select + ajax
function dynamicSelect(id1, id2) {
// Feature test to see if there is enough W3C DOM support
if (document.getElementById && document.getElementsByTagName) {
// Obtain references to both select boxes
var sel1 = document.getElementById(id1);
var sel2 = document.getElementById(id2);
// Clone the dynamic select box
var clone = sel2.cloneNode(true);
// Obtain references to all cloned options
var clonedOptions = clone.getElementsByTagName("option");
// Onload init: call a generic function to display the related options in the dynamic select box
refreshDynamicSelectOptions(sel1, sel2, clonedOptions);
// Onchange of the main select box: call a generic function to display the related options in the dynamic select box
sel1.onchange = function() {
refreshDynamicSelectOptions(sel1, sel2, clonedOptions);
};
}
}
function refreshDynamicSelectOptions(sel1, sel2, clonedOptions) {
// Delete all options of the dynamic select box
while (sel2.options.length) {
sel2.remove(0);
}
// Create regular expression objects for "select" and the value of the selected option of the main select box as class names
var pattern1 = /( |^)(select)( |$)/;
var pattern2 = new RegExp("( |^)(" + sel1.options[sel1.selectedIndex].value + ")( |$)");
// Iterate through all cloned options
for (var i = 0; i < clonedOptions.length; i++) {
// If the classname of a cloned option either equals "select" or equals the value of the selected option of the main select box
if (clonedOptions[i].className.match(pattern1) || clonedOptions[i].className.match(pattern2)) {
// Clone the option from the hidden option pool and append it to the dynamic select box
sel2.appendChild(clonedOptions[i].cloneNode(true));
}
}
}
// Attach our behavior onload
window.onload = function() {
dynamicSelect("pda-brand", "pda-type");
}
/*
http://wnas.nl/unobtrusive-dynamic-select-boxes-revisited
http://www.bobbyvandersluis.com/articles/unobtrusive_dynamic_select/index.html
-------
http://www.bobbyvandersluis.com/articles/unobtrusive_dynamic_select/unobtrusivedynamicselect_ex9.html
*/
function DynamicSelect(id1, id2) {
// Get references
this.s1 = document.getElementById(id1);
this.s2 = document.getElementById(id2);
// Parse the dependent select box and create an object representation
var o = this.s2Obj = {};
o.id = id2;
o.options = [];
var oNodes = this.s2.getElementsByTagName("option"),
ol = oNodes.length;
for (var i = 0; i < ol; i++) {
var cNodes = oNodes[i].childNodes,
cl = cNodes.length,
txt;
for (var j = 0; j < cl; j++) {
if(cNodes[j].nodeType === 3) {
txt = cNodes[j].nodeValue;
break;
}
}
o.options.push({
dataParentVal: oNodes[i].getAttribute("data-parent-value"),
val: oNodes[i].getAttribute("value"),
label: txt
});
}
//console.dir(this.s2Obj);
// Add handlers and init
var _this = this;
this.s1.onchange = function() {
_this.update();
};
this.update();
}
DynamicSelect.prototype.update = function() {
// Recreate the select box from the object
var s2New = document.createElement("select");
s2New.setAttribute("id", this.s2Obj.id);
var options = this.s2Obj.options,
ol = options.length;
for (var i = 0; i < ol; i++) {
// Only add the relevant options
if (options[i].dataParentVal === "0" || options[i].dataParentVal === this.s1.options[this.s1.selectedIndex].value) {
var oNode = document.createElement("option");
oNode.setAttribute("data-parent-value", options[i].dataParentVal);
oNode.setAttribute("value", options[i].val);
var txtNode = document.createTextNode(options[i].label);
oNode.appendChild(txtNode);
s2New.appendChild(oNode);
}
}
// Swap out old and new select elements
var s2 = document.getElementById(this.s2Obj.id);
s2.parentNode.replaceChild(s2New, s2);
};
window.onload = function() {
var pdaDynamicSelect = new DynamicSelect("pda-brand", "pda-type");
var mobilePhoneDynamicSelect = new DynamicSelect("mobile-phone-brand", "mobile-phone-type");
};
/**
* jQuery.ajax mid - CROSS DOMAIN AJAX
* ---
* @author James Padolsey (http://james.padolsey.com)
* @version 0.11
* @updated 12-JAN-10
* ---
* Note: Read the README!
* ---
* @info http://james.padolsey.com/javascript/cross-domain-requests-with-jquery/
*/
jQuery.ajax = (function(_ajax){
var protocol = location.protocol,
hostname = location.hostname,
exRegex = RegExp(protocol + '//' + hostname),
YQL = 'http' + (/^https/.test(protocol)?'s':'') + '://query.yahooapis.com/v1/public/yql?callback=?',
query = 'select * from html where url="{URL}" and xpath="*"';
function isExternal(url) {
return !exRegex.test(url) && /:\/\//.test(url);
}
return function(o) {
var url = o.url;
if ( /get/i.test(o.type) && !/json/i.test(o.dataType) && isExternal(url) ) {
// Manipulate options so that JSONP-x request is made to YQL
o.url = YQL;
o.dataType = 'json';
o.data = {
q: query.replace(
'{URL}',
url + (o.data ?
(/\?/.test(url) ? '&' : '?') + jQuery.param(o.data)
: '')
),
format: 'xml'
};
// Since it's a JSONP request
// complete === success
if (!o.success && o.complete) {
o.success = o.complete;
delete o.complete;
}
o.success = (function(_success){
return function(data) {
if (_success) {
// Fake XHR callback.
_success.call(this, {
responseText: data.results[0]
// YQL screws with <script>s
// Get rid of them
.replace(/<script[^>]+?\/>|<script(.|\s)*?\/script>/gi, '')
}, 'success');
}
};
})(o.success);
}
return _ajax.apply(this, arguments);
};
})(jQuery.ajax);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment