J'utilise JavaScript pour créer une liste déroulante personnalisée/personnalisée qui fonctionne parfaitement avec jQuery 1.3.2, mais j'ai une erreur dans 1.4.4. Je veux l'utiliser si quelqu'un peut donner une idée sur ce serait vraiment aide complète.Erreur lors du changement de jQuery 1.3.2 → 1.4.4
L'erreur
(this.change[x].call)
ne fonctionne pas.
// JavaScript Document
jQuery(document).ready(function()
{
jQuery('select.jsDropdown').each(function() { var dropdown = this; setTimeout(function() { new GenericDropdown(dropdown) }, 1) });
});
// GENERIC DROPDOWNS
GenericDropdown = function(element)
{
var _self = this;
this.element = this.element ? this.element : element;
this.field;
this.ddelement = null;
this.options = this.options ? this.options : [];
this.selectedIndex = 0;
this.width = 0;
this.position = [];
this.change = [];
this.attributes = {};
this.className = this.className ? this.className : 'jsDropdown';
this.value = null;
this.keySelected = 0;
this.eventOpen = this.eventOpen ? this.eventOpen : function(e) { _self.open(e) };
this.eventSelect = this.eventSelect ? this.eventSelect : function(e) { _self.select(e) };
this.eventKeydown = this.eventKeydown ? this.eventKeydown : function(e) { _self.keydown(e) };
this.eventClose = this.eventClose ? this.eventClose : function(e) { _self.close(e) };
this.eventCancel = this.eventCancel ? this.eventCancel : function(e) { _self.cancel(e) };
if (this.element)
{
// save options data
jQuery(this.element).find('option').each(function(i)
{
if (!_self.options[i]) _self.options[i] = [];
_self.options[i][0] = jQuery(this).val();
_self.options[i][1] = jQuery(this).text();
_self.options[i][2] = jQuery(this).attr('class')
if (this.selected) _self.selectedIndex = i;
});
// get name
var name = jQuery(this.element).attr('name');
// save attributes
var attributes = this.element.attributes;
for (var x = 0; x < attributes.length; x++) this.attributes[ attributes[x].nodeName ] = attributes[x].nodeValue;
// save class names
this.className = this.className + ' ' + this.element.className.replace(this.className, '');
// copy over events
var events = jQuery.data(this.element, 'events') ? jQuery.data(this.element, 'events')[ 'change' ] : null;
if (events) for (var handler in events) this.change.push(events[handler]);
// calculate max width
var tmp = jQuery('<div class="jsDropdownMenu" style="position:static"><ul><li style="display:inline; padding:0"></li></ul></div>');
jQuery('body').append(tmp);
for (var x = 0; x < this.options.length; x++)
{
tmp.find('li').text(this.options[x][1]);
if (tmp.find('li')[0].offsetWidth > this.width) this.width = tmp.find('li')[0].offsetWidth;
}
tmp.remove();
// draw styled dropdown
this.draw();
// save reference to object in jQuery
this.element.data('jDropdown', _self);
// create hidden field with data
this.field = jQuery('<input type="hidden" name="' + name + '" value="' + this.options[this.selectedIndex][0] + '" />');
this.element.after(this.field);
// save data into jQuery
this.element.data('name', name);
this.element.data('value', this.options[this.selectedIndex][0]);
this.element.val(this.options[this.selectedIndex][0]);
// save selected value
this.value = this.options[this.selectedIndex][0];
// bind window close event to replace normal selects for server data
// jQuery(window).bind('beforeunload', unload);
}
}
GenericDropdown.prototype.draw = function()
{
var self = this;
// get id if there is one
var id = (this.element.id) ? this.element.id : null;
var widthFactor = jQuery('#selectCatFAQ').length ? 0 : 27;
// build up dropdown
var width = (jQuery(this.element).css('width') != 'auto') ? (parseInt(jQuery(this.element).css('width')) > this.width) ? parseInt(jQuery(this.element).css('width')) - widthFactor : this.width + 5 : this.width + 5;
// setting max width for the dropdowns
width = width > 340 ? 340 : width;
var dropdown = jQuery('<a href="#" class="' + this.className + '"><span>' + this.options[this.selectedIndex][1] + '</span></a>');
// bind events
dropdown.width(width);
dropdown.bind('click', self.eventOpen);
dropdown.bind('keydown', self.eventKeydown);
spanwidth=width-17;
dropdown.find('span').css({ width:spanwidth+'px' });
if (id) dropdown.attr('id', id);
// replace existing dropdown with styled one
var select = jQuery(this.element);
this.element = jQuery(dropdown);
select.replaceWith(this.element);
// custom width set for accordion
}
GenericDropdown.prototype.unload = function()
{
var select = jQuery('<select></select>').css({ visibility:'hidden' });
// copy back attributes
jQuery.each(this.attributes, function(key, value) { select[0].setAttribute(key, value) });
// add in options
jQuery.each(this.options, function() { select.append(jQuery('<option value="' + this[0] + '">' + this[1] + '</option>')) });
// set selected option
select.find('option')[ this.selectedIndex ].selected = 'selected';
// replace jsDropdown
this.element.replaceWith(select.removeClass('jsDropdown'));
this.element = select;
}
GenericDropdown.prototype.open = function(e)
{
var self = this;
if (this.element.attr('disabled') != 'disabled')
{
// get position for dropdown
var in_popup = this.element.parents('#Popup').length ? true : false;
// This line is not working with jquery 1.4 so removing border and padding paramaters
//var jquery_offset = this.element.offset({ border:true, padding:true });
var jquery_offset = this.element.offset();
this.position = [ jquery_offset.left+2, jquery_offset.top + this.element.outerHeight()-3 ];
var width = (this.element.innerWidth() > this.width) ? this.element.innerWidth() : this.width;
var top = this.position[1];
if (in_popup && !(jQuery.browser.msie && jQuery.browser.version < 7)) top = top - jQuery(document).scrollTop();
// create dropdown
this.ddelement = jQuery('<div class="jsDropdownMenu"><div class="top-content"><ul class="content"></ul></div></div>').css({ width:width-6 });
this.ddelement.css({ top:top, left:this.position[0]+0+'px' });
if (in_popup && !(jQuery.browser.msie && jQuery.browser.version < 7)) this.ddelement.css({ position:'fixed' });
if (jQuery.browser.msie && jQuery.browser.version < 7 && in_popup) { var dd = this.ddelement; jQuery(window).bind('scroll', function() { dd.css({ top:top + jQuery(document).scrollTop() }) }) };
for (var x = 0; x < this.options.length; x++)
{
var item = jQuery('<li><span>' + this.options[x][1] + '</span></li>');
if (x == this.selectedIndex) item.addClass('selected');
if (this.options[x][2]) item.addClass(this.options[x][2])
item.bind('click', self.eventSelect);
item.bind('mouseover', function(e)
{
self.ddelement.find('li.selected').removeClass('selected');
jQuery(this).addClass('selected');
self.keySelected = self.ddelement.find('li').index(this);
});
this.ddelement.find('ul.content').append(item);
}
// append dropdown to container
jQuery('body').append(this.ddelement);
// remove open event and add cancel event
this.element.unbind('click', self.eventOpen);
this.element.bind('click', self.eventCancel);
// add close event
setTimeout(function() { jQuery('body').bind('click', self.eventClose) }, 1);
//jQuery('.jsDropdownMenu .first span').append(this.options[this.selectedIndex][1])
}
// e.stopPropagation();
e.preventDefault();
}
GenericDropdown.prototype.keydown = function(e)
{
if (e.keyCode == 32) // space
{
if (!this.ddelement)
{
this.keySelected = this.selectedIndex;
this.open(e);
}
else
{
this.ddelement.find('li.selected').click();
e.preventDefault();
}
}
else if (e.keyCode == 40) // down
{
if (++this.keySelected > this.options.length - 1) this.keySelected = 0;
if (this.ddelement)
{
this.ddelement.find('li.selected').removeClass('selected');
this.ddelement.find('li:eq(' + this.keySelected + ')').addClass('selected');
}
else
{
this.selectedIndex = this.keySelected;
// set text dropdown
this.element.find('span').text(this.options[this.selectedIndex][1]);
// save value in jQuery
this.element.data('value', this.options[this.selectedIndex][0]);
// save selected value
this.value = this.options[this.selectedIndex][0];
this.element.val(this.options[this.selectedIndex][0]);
this.field.val(this.options[this.selectedIndex][0]);
// perform custom event listeners if they exist
e.target = this.element[0];
if (this.change.length) for (var x = 0; x < this.change.length; x++) this.change[x].call(this, e);
}
e.preventDefault();
}
else if (e.keyCode == 38) // up
{
if (--this.keySelected < 0) this.keySelected = this.options.length - 1;
if (this.ddelement)
{
this.ddelement.find('li.selected').removeClass('selected');
this.ddelement.find('li:eq(' + this.keySelected + ')').addClass('selected');
}
else
{
this.selectedIndex = this.keySelected;
// set text dropdown
this.element.find('span').text(this.options[this.selectedIndex][1]);
// save value in jQuery
this.element.data('value', this.options[this.selectedIndex][0]);
// save selected value
this.value = this.options[this.selectedIndex][0];
this.element.val(this.options[this.selectedIndex][0]);
this.field.val(this.options[this.selectedIndex][0]);
// perform custom event listeners if they exist
e.target = this.element[0];
if (this.change.length) for (var x = 0; x < this.change.length; x++) this.change[x].call(this, e);
}
e.preventDefault();
}
else if (e.keyCode == 13) // return
{
this.ddelement.find('li:eq(' + this.keySelected + ')').click();
e.preventDefault();
}
else if (e.keyCode == 9 && this.ddelement) // tab
{
this.ddelement.find('li:eq(' + this.keySelected + ')').click();
}
}
GenericDropdown.prototype.select = function(e)
{
// get index of selected item
var new_selection = -1;
var target_li = e.target;
if (target_li.nodeName != 'LI') target_li = jQuery(target_li).parents('li')[0];
var list_items = this.ddelement.find('li');
for (var x = 0; x < list_items.length; x++) if (list_items[x] == target_li) { new_selection = x; break }
if (new_selection != this.selectedIndex)
{
this.selectedIndex = new_selection;
// set text dropdown
this.element.find('span').html(this.options[this.selectedIndex][1]);
// save value in jQuery
this.element.data('value', this.options[this.selectedIndex][0]);
// save selected value
this.value = this.options[this.selectedIndex][0];
this.element.val(this.options[this.selectedIndex][0]);
this.field.val(this.options[this.selectedIndex][0]);
// perform custom event listeners if they exist
e.target = this.element[0];
if (this.change.length); for (var x = 0; x < this.change.length; x++) this.change[x].call(this, e);
}
this.eventClose(e);
e.stopPropagation();
e.preventDefault();
}
GenericDropdown.prototype.close = function(e)
{
var self = this;
this.ddelement.remove();
delete this.ddelement;
// remove close event
jQuery('body').unbind('click', self.eventClose);
// add open event and remove cancel event
setTimeout(function() { self.element.bind('click', self.eventOpen) }, 1);
this.element.unbind('click', self.eventCancel);
if (e) e.preventDefault();
}
GenericDropdown.prototype.cancel = function(e)
{
this.eventClose(e);
e.stopPropagation();
}
GenericDropdown.prototype.reset = function(dropdown)
{
var select = jQuery('<select></select>');
// copy back attributes
jQuery.each(this.attributes, function(key, value) { select[0].setAttribute(key, value) });
if (dropdown.id) select[0].id = dropdown.id;
// add in options
jQuery.each(this.options, function() { select.append(jQuery('<option value="' + this[0] + '">' + this[1] + '</option>')) });
// set selected option
select.find('option')[ this.selectedIndex ].selected = 'selected';
// replace jsDropdown
jQuery(dropdown).replaceWith(select.removeClass('jsDropdown'));
// remove adjacent hidden field
select.next('input[type=hidden]').remove();
return select[0];
}
Si vous utilisez également jQuery ui, vous pouvez jeter un oeil au widget 'selectmenu'. Ce lien aurait pu être plus utile lorsque vous avez démarré ce projet :-) https://github.com/fnagel/jquery-ui – prodigitalson
Avez-vous déjà fait du débogage, disons avec Firebug et la version non-minifiée de la bibliothèque jQuery ? – Pointy
Salut, Oui j'ai essayé un débogage pas réussi. Vous pouvez télécharger ma version non-minifiée de javascript à partir d'ici. http://www.educationuk.org/js/genericDropdown.js. –