| 1 |
// $Id: activeselect.js,v 1.16 2006/04/09 05:11:52 jaza Exp $ |
// $Id: activeselect.js,v 1.17 2006/04/14 15:07:50 jaza Exp $ |
|
|
|
|
// Global Killswitch |
|
|
if (isJsEnabled()) { |
|
|
addLoadEvent(activeselectAutoAttach); |
|
|
} |
|
| 2 |
|
|
| 3 |
/** |
/** |
| 4 |
* Attaches the activeselect behaviour to all required fields |
* Attaches the activeselect behaviour to all required fields |
| 5 |
*/ |
*/ |
| 6 |
function activeselectAutoAttach() { |
Drupal.activeselectAutoAttach = function () { |
| 7 |
var asdb = []; |
var asdb = []; |
| 8 |
var inputs = document.getElementsByTagName('input'); |
$('input.activeselect-path').each(function () { |
| 9 |
var input = null; |
var index = this.id.substr(0, this.id.length - 18); |
| 10 |
for (var i = 0; input = inputs[i]; i++) { |
var uri = this.value +'/'+ encodeURIComponent(index).substr(5); |
| 11 |
if (input && hasClass(input, 'activeselect-path')) { |
var extra = $('#' + index + '-activeselect-extra').val(); |
| 12 |
var index = input.id.substr(0, input.id.length - 18); |
var targets = $('#' + index + '-activeselect-targets').val(); |
| 13 |
var uri = input.value +'/'+ encodeURIComponent(index).substr(5); |
var input = $('#' + index).get(0); |
|
input = $(index + '-activeselect-extra'); |
|
|
var extra = input.value; |
|
|
input = $(index + '-activeselect-targets'); |
|
|
var targets = input.value; |
|
|
input = $(index); |
|
|
if (!asdb[uri]) { |
|
|
asdb[uri] = new ASDB(uri, targets); |
|
|
} |
|
| 14 |
|
|
| 15 |
new jsAS(input, asdb[uri], targets, extra); |
if (!asdb[uri]) { |
| 16 |
|
asdb[uri] = new Drupal.ASDB(uri, targets); |
| 17 |
} |
} |
| 18 |
} |
new Drupal.jsAS(input, asdb[uri], targets, extra); |
| 19 |
|
}); |
| 20 |
} |
} |
| 21 |
|
|
| 22 |
/** |
/** |
| 23 |
* An ActiveSelect object |
* An ActiveSelect object |
| 24 |
*/ |
*/ |
| 25 |
function jsAS(input, db, targets, extra) { |
Drupal.jsAS = function (input, db, targets, extra) { |
| 26 |
var as = this; |
var as = this; |
| 27 |
this.input = input; |
this.input = input; |
| 28 |
this.db = db; |
this.db = db; |
| 29 |
this.input.onchange = function (event) { return as.onchange(this, event); }; |
$(this.input).change(function (event) { return as.onchange(this, event); }); |
| 30 |
this.extra = extra; |
this.extra = extra; |
| 31 |
var targetsArray = targets.split(','); |
var targetsArray = targets.split(','); |
| 32 |
this.targets = []; |
this.targets = []; |
| 33 |
for (var target = 0; target < targetsArray.length; target++) { |
for (var target = 0; target < targetsArray.length; target++) { |
| 34 |
var newTarget = $(targetsArray[target]); |
var newTarget = $('#' + targetsArray[target]).get(0); |
| 35 |
newTarget.owner = this; |
newTarget.owner = this; |
| 36 |
this.targets.push(newTarget); |
this.targets.push(newTarget); |
| 37 |
} |
} |
| 45 |
/** |
/** |
| 46 |
* Handler for the "onchange" event |
* Handler for the "onchange" event |
| 47 |
*/ |
*/ |
| 48 |
jsAS.prototype.onchange = function (input, e) { |
Drupal.jsAS.prototype.onchange = function (input, e) { |
| 49 |
if (!e) { |
if (!e) { |
| 50 |
e = window.event; |
e = window.event; |
| 51 |
} |
} |
| 56 |
/** |
/** |
| 57 |
* Return the currently selected options as a pipe-delimited string |
* Return the currently selected options as a pipe-delimited string |
| 58 |
*/ |
*/ |
| 59 |
jsAS.prototype.getSelectedOptions = function () { |
Drupal.jsAS.prototype.getSelectedOptions = function () { |
| 60 |
var selectedOptions = []; |
var selectedOptions = []; |
| 61 |
var maxWidth = 0; |
var maxWidth = 0; |
| 62 |
for (var i = 0; i < this.input.options.length; i++) { |
$('#' + this.input.id + ' option').each(function () { |
| 63 |
if (this.input.options[i].selected) { |
if (this.selected) { |
| 64 |
var optionString = this.input.options[i].value.replace(/\|/g, '|') +'|'+ this.input.options[i].text.replace(/\|/g, '|'); |
var optionString = this.value.replace(/\|/g, '|') +'|'+ this.text.replace(/\|/g, '|'); |
| 65 |
selectedOptions.push(optionString); |
selectedOptions.push(optionString); |
| 66 |
} |
} |
| 67 |
if (this.input.options[i].text.length > maxWidth) { |
if (this.text.length > maxWidth) { |
| 68 |
maxWidth = this.input.options[i].text.length; |
maxWidth = this.text.length; |
| 69 |
} |
} |
| 70 |
} |
}); |
| 71 |
this.setSelectWidth(maxWidth); |
this.setSelectWidth(maxWidth); |
| 72 |
|
|
| 73 |
return selectedOptions.join('||'); |
return selectedOptions.join('||'); |
| 74 |
} |
} |
| 75 |
|
|
| 76 |
/** |
/** |
| 77 |
* Sets the width of the activeselect element, and adjusts the position of the |
* Sets the width and background position of the activeselect element. |
|
* throbber background image |
|
| 78 |
*/ |
*/ |
| 79 |
jsAS.prototype.setSelectWidth = function (width) { |
Drupal.jsAS.prototype.setSelectWidth = function (width) { |
| 80 |
if (width != null) { |
if (width != null) { |
| 81 |
this.selectWidth = ((width * 10) * 1.5) + 20; |
this.selectWidth = ((width * 10) * 1.5) + 20; |
| 82 |
} |
} |
| 83 |
this.input.style.width = this.selectWidth +'px'; |
$(this.input).css({ |
| 84 |
this.input.style.backgroundPosition = (this.selectWidth - 35) +'px 2px'; |
width: this.selectWidth +'px', |
| 85 |
|
backgroundPosition: (this.selectWidth - 35) +'px 2px' |
| 86 |
|
}); |
| 87 |
} |
} |
| 88 |
|
|
| 89 |
/** |
/** |
| 90 |
* Sets the width of the specified target element |
* Sets the width of the specified target element |
| 91 |
*/ |
*/ |
| 92 |
jsAS.prototype.setTargetWidth = function (target, width) { |
Drupal.jsAS.prototype.setTargetWidth = function (target, width) { |
| 93 |
if (width != null) { |
if (width != null) { |
| 94 |
this.targets[target].targetWidth = (width * 10) * 1.2; |
this.targets[target].targetWidth = (width * 10) * 1.2; |
| 95 |
} |
} |
| 96 |
this.targets[target].style.width = this.targets[target].targetWidth +'px'; |
$(this.targets[target]).css({ |
| 97 |
|
width: this.targets[target].targetWidth +'px' |
| 98 |
|
}); |
| 99 |
} |
} |
| 100 |
|
|
| 101 |
/** |
/** |
| 102 |
* Starts a search |
* Starts a search |
| 103 |
*/ |
*/ |
| 104 |
jsAS.prototype.populateTargets = function () { |
Drupal.jsAS.prototype.populateTargets = function () { |
| 105 |
var as = this; |
var as = this; |
| 106 |
this.db.owner = this; |
this.db.owner = this; |
| 107 |
|
|
| 111 |
/** |
/** |
| 112 |
* Fills the target select boxes with any matches received |
* Fills the target select boxes with any matches received |
| 113 |
*/ |
*/ |
| 114 |
jsAS.prototype.populate = function (matches) { |
Drupal.jsAS.prototype.populate = function (matches) { |
| 115 |
for (targetIndex in this.targets) { |
for (targetIndex in this.targets) { |
| 116 |
var target = this.targets[targetIndex]; |
var target = this.targets[targetIndex]; |
| 117 |
var matchesTarget = 0; |
var matchesTarget = 0; |
| 135 |
} |
} |
| 136 |
} |
} |
| 137 |
|
|
| 138 |
while (target.hasChildNodes()) { |
$(target).empty(); |
|
target.removeChild(target.childNodes[0]); |
|
|
} |
|
| 139 |
var targetMatches = matches[matchesTarget]['options']; |
var targetMatches = matches[matchesTarget]['options']; |
| 140 |
var maxWidth = 0; |
var maxWidth = 0; |
| 141 |
for (currMatch in targetMatches) { |
for (currMatch in targetMatches) { |
| 149 |
// 'new Option()' used instead of appendChild(), because IE6 refuses to |
// 'new Option()' used instead of appendChild(), because IE6 refuses to |
| 150 |
// display option text if the latter method is used (otherwise they seem |
// display option text if the latter method is used (otherwise they seem |
| 151 |
// to behave the same). |
// to behave the same). |
| 152 |
this.targets[targetIndex].options[this.targets[targetIndex].options.length] = new Option(text, value, false, selected); |
$(this.targets[targetIndex]).append(new Option(text, value, false, selected)); |
| 153 |
if (selected && !this.targets[targetIndex].multiple) { |
if (selected && !this.targets[targetIndex].multiple) { |
| 154 |
this.targets[targetIndex].selectedIndex = this.targets[targetIndex].options.length-1; |
this.targets[targetIndex].selectedIndex = this.targets[targetIndex].options.length-1; |
| 155 |
} |
} |
| 158 |
this.targets[targetIndex].selectedIndex = 0; |
this.targets[targetIndex].selectedIndex = 0; |
| 159 |
} |
} |
| 160 |
|
|
| 161 |
if (hasClass(this.targets[targetIndex], 'form-activeselect')) { |
if (this.hasClass(this.targets[targetIndex], 'form-activeselect')) { |
| 162 |
// Since IE does not support the DOM 2 methods for manually firing an |
// Since IE does not support the DOM 2 methods for manually firing an |
| 163 |
// event, we must cater especially to its needs. |
// event, we must cater especially to its needs. |
| 164 |
// Reference: http://www.howtocreate.co.uk/tutorials/javascript/domevents |
// Reference: http://www.howtocreate.co.uk/tutorials/javascript/domevents |
| 185 |
} |
} |
| 186 |
|
|
| 187 |
/** |
/** |
| 188 |
|
* Returns true if an element has a specified class name |
| 189 |
|
*/ |
| 190 |
|
Drupal.jsAS.prototype.hasClass = function (node, className) { |
| 191 |
|
if (node.className == className) { |
| 192 |
|
return true; |
| 193 |
|
} |
| 194 |
|
var reg = new RegExp('(^| )'+ className +'($| )') |
| 195 |
|
if (reg.test(node.className)) { |
| 196 |
|
return true; |
| 197 |
|
} |
| 198 |
|
return false; |
| 199 |
|
} |
| 200 |
|
|
| 201 |
|
/** |
| 202 |
* An ActiveSelect DataBase object |
* An ActiveSelect DataBase object |
| 203 |
*/ |
*/ |
| 204 |
function ASDB(uri, targets) { |
Drupal.ASDB = function (uri, targets) { |
| 205 |
this.uri = uri; |
this.uri = uri; |
| 206 |
this.targets = targets; |
this.targets = targets; |
| 207 |
this.delay = 300; |
this.delay = 300; |
| 211 |
/** |
/** |
| 212 |
* Performs a cached and delayed search |
* Performs a cached and delayed search |
| 213 |
*/ |
*/ |
| 214 |
ASDB.prototype.search = function(searchString, targets, extra) { |
Drupal.ASDB.prototype.search = function(searchString, targets, extra) { |
| 215 |
this.searchString = searchString; |
this.searchString = searchString; |
| 216 |
if (this.cache[searchString]) { |
if (this.cache[searchString]) { |
| 217 |
return this.owner.populate(this.cache[searchString]); |
return this.owner.populate(this.cache[searchString]); |
| 221 |
} |
} |
| 222 |
var db = this; |
var db = this; |
| 223 |
this.timer = setTimeout(function() { |
this.timer = setTimeout(function() { |
| 224 |
db.owner.input.style.width = db.owner.selectWidth +'px'; |
$(db.owner.input).css({ |
| 225 |
db.owner.input.style.backgroundPosition = (db.owner.selectWidth - 35) +'px -18px'; |
width: db.owner.selectWidth +'px', |
| 226 |
|
backgroundPosition: (db.owner.selectWidth - 35) +'px -18px' |
| 227 |
|
}); |
| 228 |
var targetIds = []; |
var targetIds = []; |
| 229 |
for (var target = 0; target < targets.length; target++) { |
for (var target = 0; target < targets.length; target++) { |
| 230 |
if (targets[target].id) { |
if (targets[target].id) { |
| 231 |
targetIds.push(targets[target].id.substr(5)); |
targetIds.push($(targets[target]).id().substr(5)); |
| 232 |
} |
} |
| 233 |
} |
} |
| 234 |
var targetsString = targetIds.join(','); |
var targetsString = targetIds.join(','); |
| 235 |
var uri = db.uri +'/'+ encodeURIComponent(targetsString) +'/'+ encodeURIComponent(searchString); |
|
| 236 |
uri += '/'+ encodeURIComponent(extra); |
// Ajax GET request for activeselect |
| 237 |
HTTPGet(uri, db.receive, db); |
$.ajax({ |
| 238 |
|
type: "GET", |
| 239 |
|
url: db.uri +'/'+ encodeURIComponent(targetsString) +'/'+ encodeURIComponent(searchString) +'/'+ encodeURIComponent(extra), |
| 240 |
|
success: function (data) { |
| 241 |
|
// Split into array of key->value pairs |
| 242 |
|
if (data.length > 0) { |
| 243 |
|
var targets = Drupal.parseJson(data); |
| 244 |
|
if (typeof targets['status'] == 'undefined' || targets['status'] != 0) { |
| 245 |
|
db.cache[searchString] = targets; |
| 246 |
|
db.owner.populate(targets); |
| 247 |
|
} |
| 248 |
|
} |
| 249 |
|
}, |
| 250 |
|
error: function (xmlhttp) { |
| 251 |
|
asdb.owner.setSelectWidth(null); |
| 252 |
|
alert('An HTTP error '+ xmlhttp.status +' occured.\n'+ db.uri); |
| 253 |
|
} |
| 254 |
|
}); |
| 255 |
}, this.delay); |
}, this.delay); |
| 256 |
} |
} |
| 257 |
|
|
| 258 |
/** |
// Global Killswitch |
| 259 |
* HTTP callback function. Passes select options to the activeselect object |
if (Drupal.jsEnabled) { |
| 260 |
*/ |
$(document).ready(Drupal.activeselectAutoAttach); |
|
ASDB.prototype.receive = function(string, xmlhttp, asdb) { |
|
|
// Note: Safari returns 'undefined' status if the request returns no data. |
|
|
if (xmlhttp.status != 200 && typeof xmlhttp.status != 'undefined') { |
|
|
asdb.owner.setSelectWidth(null); |
|
|
return alert('An HTTP error '+ xmlhttp.status +' occured.\n'+ asdb.uri); |
|
|
} |
|
|
// Split into array of key->value pairs |
|
|
if (string.length > 0) { |
|
|
var targets = parseJson(string); |
|
|
if (typeof targets['status'] == 'undefined' || targets['status'] != 0) { |
|
|
asdb.cache[asdb.searchString] = targets; |
|
|
asdb.owner.populate(targets); |
|
|
} |
|
|
} |
|
| 261 |
} |
} |