/* =========================================================== * * Name: selectordie.js * Updated: 2014-07-08 * Version: 0.1.4 * Created by: Per V @ Vst.mn * What?: The Select or Die JS * * Copyright (c) 2014 Per Vestman * Dual licensed under the MIT and GPL licenses. * * To much comments in the code. Please, I know. * * Oddny | Cogs 'n Kegs * * =========================================================== */ ; (function ($) { $.fn.selectOrDie = function (method) { "use strict"; var $defaults = { customID: null, // String - "" by default - Adds an ID to the SoD customClass: "", // String - "" by default - Adds a class to the SoD placeholder: null, // String - "" by default - Adds a placeholder that will be shown before a selection has been made prefix: null, // String - "" by default - Adds a prefix that always will be shown before the selected value cycle: false, // Boolean - false by default - Should keyboard cycle through options or not? links: false, // Boolean - false by default - Should the options be treated as links? linksExternal: false, // Boolean - false by default - Should the options be treated as links and open in a new window/tab? size: 0, // Integer - 0 by default - The value set equals the amount of items before scroll is needed tabIndex: 0, // integer - 0 by default onChange: $.noop // Adds a callback function for when the SoD gets changed }, $_settings = {}, $_sodFilterTimeout, $_sodViewportTimeout; var _private = { initSoD: function (options) { $_settings = $.extend({}, $defaults, options); return this.each(function (i) { if ( !$(this).parent().hasClass("sod_select") ) { var $select = $(this), $settingsId = $_settings.customID ? $_settings.customID : ( $select.data("custom-id") ? $select.data("custom-id") : $_settings.customID ), $settingsClass = $_settings.customClass ? $_settings.customClass : ( $select.data("custom-class") ? $select.data("custom-class") : $_settings.customClass ), $settingsPrefix = $_settings.prefix ? $_settings.prefix : ( $select.data("prefix") ? $select.data("prefix") : $_settings.prefix ), $settingsPlaceholder = $_settings.placeholder ? $_settings.placeholder : ( $select.data("placeholder") ? $select.data("placeholder") : $_settings.placeholder ), $settingsCycle = ( $_settings.cycle || $select.data("cycle") ) ? true : $_settings.cycle, $settingsLinks = ( $_settings.links || $select.data("links") ) ? true : $_settings.links, $settingsLinksExternal = ( $_settings.linksExternal || $select.data("links-external") ) ? true : $_settings.linksExternal, $settingsSize = $_settings.size ? $_settings.size : ( $select.data("size") ? $select.data("size") : $_settings.size ), $settingsTabIndex = $_settings.tabIndex ? $_settings.tabIndex : ( $select.data("tabindex") ? $select.data("tabindex") : ( $select.attr("tabindex") ? $select.attr("tabindex") : $_settings.tabIndex ) ), $selectTitle = $select.prop("title") ? $select.prop("title") : null, $selectDisabled = $select.is(":disabled") ? " disabled" : "", $sodPrefix = "", $sodHtml = "", $sodHeight = 0, $sod, $sodListWrapper, $sodList; // If there's a prefix defined if ( $settingsPrefix ) { $sodPrefix = "" + $settingsPrefix + " "; } // If there's a placeholder defined if ( $settingsPlaceholder && !$settingsPrefix ) { $sodHtml += "" + $settingsPlaceholder + ""; } else { $sodHtml += "" + $sodPrefix + ""; } // Inserts a new element that will act like our new into the SoD element $select.appendTo( $sod ); // Bind events to the SoD $sod.on("focusin", _private.focusSod) .on("click", _private.triggerSod) .on("click", ".sod_option", _private.optionClick) .on("mousemove", ".sod_option", _private.optionHover) .on("keydown keypress", _private.keyboardUse); // Bind change event to the $select.off("change"); // Restore DOM $sod.find("span").remove(); $select.unwrap(); } else { console.log("Select or Die: There's no SoD to destroy"); } }); }, // destroy update: function () { return this.each(function (i) { var $select = $(this), $sod = $select.parent(), $sodList = $sod.find(".sod_list:first"); // Check for the SoD if ( $sod.hasClass("sod_select") ) { // Empty current list of options in faux $("option[value='" + $value + "'], optgroup[label='" + $value + "']", this).prop("disabled", true); } else if ( $sod.hasClass("sod_select") ) { // Disable select/SoD $sod.addClass("disabled"); $select.prop("disabled", true); } } else { console.log("Select or Die: There's no SoD to disable"); } }); }, // disable enable: function ($value) { return this.each(function (i) { var $select = $(this), $sod = $select.parent(); // Check for the SoD if ( $sod.hasClass("sod_select") ) { if ( typeof $value !== "undefined" ) { // Enable option/optgroup // Enables the option (and possible children if optgroup) in the SoD $sod.find(".sod_list:first .sod_option[data-value='" + $value + "']").removeClass("disabled"); $sod.find(".sod_list:first .sod_option[data-label='" + $value + "']").nextUntil(":not(.groupchild)").removeClass("disabled"); // Enables the option in the real