(function (factory) {
if (typeof define === "function" && define.amd) {
/** AMD. Register as an anonymous module. */
define(["jquery"], factory);
} else if (typeof module === "object" && module.exports) {
/** Node/CommonJS */
module.exports = factory(require("jquery"));
} else {
/** Browser globals */
factory(window.jQuery);
}
}(function ($) {
$.fn.ddslick = function (method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === "object" || !method) {
return methods.init.apply(this, arguments);
} else {
$.error("Method " + method + " does not exists.");
}
};
var methods = {};
var settingsMap = {};
var defaults = {
data: [],
keepJSONItemsOnTop: false,
animationTime: 50,
width: "20em",
height: null,
background: "#eee",
selectText: "",
defaultSelectedIndex: null,
truncateDescription: true,
imagePosition: "left",
showSelectedHTML: true,
clickOffToClose: true,
embedCSS: true,
onSelected: function() { }
};
var closeListenerInitialized = false;
var ddSelectHtml = "
";
var ddOptionsHtml = "
";
//CSS for ddSlick
var ddslickCSS = "";
//Public methods
methods.init = function (userOptions) {
//Preserve the original defaults by passing an empty object as the target
//The object is used to get global flags like embedCSS.
var options = $.extend({}, defaults, userOptions);
//CSS styles are only added once.
if ($("#css-ddslick").length <= 0 && options.embedCSS) {
$(ddslickCSS).appendTo("head");
}
//Apply on all selected elements
return this.each(function() {
//Preserve the original defaults by passing an empty object as the target
//The object is used to save drop-down"s corresponding settings and data.
var options = $.extend({}, defaults, userOptions);
var obj = $(this),
data = obj.data("ddslick");
//If the plugin has not been initialized yet
if (!data) {
var ddSelect = [];
//Get data from HTML select options
obj.find("option").each(function() {
var $this = $(this), thisData = $this.data();
ddSelect.push({
text: $.trim($this.text()),
value: $this.val(),
selected: $this.is(":selected"),
description: thisData.description,
imageSrc: thisData.imagesrc //keep it lowercase for HTML5 data-attributes
});
});
//Update Plugin data merging both HTML select data and JSON data for the dropdown
if (options.keepJSONItemsOnTop)
$.merge(options.data, ddSelect);
else options.data = $.merge(ddSelect, options.data);
//Replace HTML select with empty placeholder, keep the original
var original = obj, placeholder = $("
").attr("id", obj.attr("id"));
obj.replaceWith(placeholder);
obj = placeholder;
// Save options
var settingsId = "ID_" + (new Date()).getTime();
$(obj).attr("data-settings-id", settingsId);
settingsMap[settingsId] = {};
$.extend(settingsMap[settingsId], options);
//Add classes and append ddSelectHtml & ddOptionsHtml to the container
obj.addClass("dd-container").append(ddSelectHtml).append(ddOptionsHtml);
// Inherit name attribute from original element
obj.find("input.dd-selected-value")
.attr("id", $(original).attr("id"))
.attr("name", $(original).attr("name"));
//Get newly created ddOptions and ddSelect to manipulate
var ddOptions = obj.find(".dd-options");
ddSelect = obj.find(".dd-select");
var ddSelected = obj.find(".dd-selected");
// Add accessibility controls.
ddSelected.attr("aria-haspopup", "listbox");
ddSelected.attr("aria-expanded", "false");
ddSelected.attr("aria-controls", "dd-options-" + settingsId);
ddOptions.attr("id", "dd-options-" + settingsId);
ddOptions.attr("role", "listbox");
ddOptions.attr("tabindex", "-1");
ddOptions.attr("aria-label", "select options");
ddOptions.attr("aria-hidden", "true");
//Set widths
ddOptions.css({ width: options.width });
ddSelect.css({ width: options.width, background: options.background });
obj.css({ width: options.width });
//Set height
if (options.height !== null)
ddOptions.css({ height: options.height, overflow: "auto" });
//Add ddOptions to the container. Replace with template engine later.
$.each(options.data, function (index, item) {
if (item.selected) options.defaultSelectedIndex = index;
var ddOption = $("