| 1 |
(function(){ |
| 2 |
(function($, window, document, undefined) { |
| 3 |
"use strict"; |
| 4 |
var pluginName = "jltmaVisualSelect", defaults = { |
| 5 |
item: "jltma-select-item", |
| 6 |
selected: "jltma-selected", |
| 7 |
caption: "jltma-select-caption", |
| 8 |
container: "jltma-visual-select", |
| 9 |
insertCaption: false, |
| 10 |
insertSymbol: true, |
| 11 |
insertTitleAttr: true, |
| 12 |
autoHideElement: true, |
| 13 |
imgTest: /\.jpg|\.png|\.gif|.jpeg|\.svg/ |
| 14 |
}, attributesMap = { |
| 15 |
"type": "symbolType", |
| 16 |
"title-attr": "insertTitleAttr", |
| 17 |
"auto-hide": "autoHideElement", |
| 18 |
"caption": "insertCaption" |
| 19 |
}; |
| 20 |
function Plugin(element, options) { |
| 21 |
this.element = element; |
| 22 |
this.$element = $(element); |
| 23 |
this.options = $.extend({}, defaults, options); |
| 24 |
for (var key in attributesMap) { |
| 25 |
var value = attributesMap[key], dataAttr = this.$element.data(key); |
| 26 |
if (dataAttr === undefined) continue; |
| 27 |
this.options[value] = dataAttr; |
| 28 |
} |
| 29 |
this._defaults = defaults; |
| 30 |
this._name = pluginName; |
| 31 |
this.init(); |
| 32 |
} |
| 33 |
$.extend(Plugin.prototype, { |
| 34 |
init: function() { |
| 35 |
var self = this, st = self.options; |
| 36 |
self.multiple = self.$element.attr("multiple") === "multiple"; |
| 37 |
if (st.autoHideElement) self.$element.css("display", "none"); |
| 38 |
self.$selectCont = $("<div class=\"" + st.container + "\"></div>").insertAfter(self.$element); |
| 39 |
self.generate(); |
| 40 |
self.$element.on("change", this.update.bind(this)); |
| 41 |
}, |
| 42 |
/** |
| 43 |
* on visual select item clicked |
| 44 |
* @private |
| 45 |
* @param {jQuery Event} event |
| 46 |
*/ |
| 47 |
_onItemClick: function(event) { |
| 48 |
var $visualItem = $(event.currentTarget), $selectOption = $visualItem.data("selectOption"), st = this.options; |
| 49 |
if (this.multiple) if ($visualItem.hasClass(st.selected)) { |
| 50 |
$visualItem.removeClass(st.selected); |
| 51 |
$selectOption.removeAttr("selected"); |
| 52 |
} else { |
| 53 |
$visualItem.addClass(st.selected); |
| 54 |
$selectOption.attr("selected", "selected"); |
| 55 |
var val = this.$element.val(); |
| 56 |
if (val === null) val = []; |
| 57 |
val.push($selectOption.attr("value")); |
| 58 |
this.$element.val(val); |
| 59 |
} |
| 60 |
else if (!$visualItem.hasClass(st.selected)) { |
| 61 |
$visualItem.addClass(st.selected); |
| 62 |
$selectOption.attr("selected", "selected"); |
| 63 |
this.$element.val($selectOption.attr("value")); |
| 64 |
if (this.$selectedItem) { |
| 65 |
this.$selectedItem.removeClass(st.selected); |
| 66 |
this.$selectedItem.data("selectOption").removeAttr("selected"); |
| 67 |
} |
| 68 |
this.$selectedItem = $visualItem; |
| 69 |
} |
| 70 |
this._internalTrigger = true; |
| 71 |
this.$element.trigger("change"); |
| 72 |
}, |
| 73 |
/** |
| 74 |
* Generates video element sources by parsing the data-video-src attribute on element |
| 75 |
*/ |
| 76 |
_generateVideoSource: function(videoSrc) { |
| 77 |
var source = ""; |
| 78 |
videoSrc.split(",").forEach(function(src) { |
| 79 |
src = src.split(" "); |
| 80 |
source += "<source src=\"" + src[0] + "\" type=\"video/" + src[1] + "\">"; |
| 81 |
}); |
| 82 |
return source; |
| 83 |
}, |
| 84 |
/** |
| 85 |
* On video ready to play |
| 86 |
*/ |
| 87 |
_videoInit: function(event) { |
| 88 |
$(event.currentTarget).on("mouseenter", function() { |
| 89 |
this.play(); |
| 90 |
}).on("mouseleave", function() { |
| 91 |
this.pause(); |
| 92 |
this.currentTime = 0; |
| 93 |
}); |
| 94 |
}, |
| 95 |
/** |
| 96 |
* updates selected items in visual form |
| 97 |
*/ |
| 98 |
update: function() { |
| 99 |
if (this._internalTrigger) { |
| 100 |
this._internalTrigger = false; |
| 101 |
return; |
| 102 |
} |
| 103 |
var self = this, st = this.options, $items = self.$selectCont.find("." + st.item), val = self.$element.val(); |
| 104 |
self.$element.find("option").each(function(index, option) { |
| 105 |
var $option = $(option), $visualItem = $items.eq(index); |
| 106 |
if (val.indexOf($option.val()) !== -1) self.$selectedItem = $visualItem.addClass(st.selected); |
| 107 |
else $visualItem.removeClass(st.selected); |
| 108 |
}); |
| 109 |
}, |
| 110 |
/** |
| 111 |
* create visual items from HTML select element |
| 112 |
* @param {boolean} reset Remove old visual items [it's useful for updating visual select] |
| 113 |
* @public |
| 114 |
*/ |
| 115 |
generate: function(reset) { |
| 116 |
var self = this, st = self.options; |
| 117 |
if (reset) this.$selectCont.find("." + st.item).remove(); |
| 118 |
self.$element.find("option").each(function() { |
| 119 |
var $selectOption = $(this), $visualItem = $("<div class=\"" + st.item + "\"></div>"), symbol = $selectOption.data("symbol"), videoSrc = $selectOption.data("video-src"), caption = $selectOption.html(), cssClass = $selectOption.data("class"); |
| 120 |
if (cssClass) $visualItem.addClass(cssClass); |
| 121 |
if (st.insertSymbol) if (videoSrc) { |
| 122 |
$visualItem.attr("item-type", "video"); |
| 123 |
$("<video></video>").attr("muted", "").attr("loop", "").append(self._generateVideoSource(videoSrc)).appendTo($visualItem)[0].addEventListener("loadedmetadata", self._videoInit); |
| 124 |
} else if (st.imgTest.test(symbol) || $selectOption.data("type") === "image") $("<img/>").attr("src", symbol).attr("alt", caption).appendTo($visualItem); |
| 125 |
else $("<span></span>").addClass(symbol).appendTo($visualItem); |
| 126 |
if (st.insertCaption) $("<span class=\"" + st.caption + "\">" + caption + "</span>").appendTo($visualItem); |
| 127 |
$visualItem.click($.proxy(self._onItemClick, self)).data("selectOption", $selectOption).appendTo(self.$selectCont); |
| 128 |
if (st.insertTitleAttr) $visualItem.attr("title", caption); |
| 129 |
if ($selectOption.attr("selected") === "selected") self.$selectedItem = $visualItem.addClass(st.selected); |
| 130 |
}); |
| 131 |
} |
| 132 |
}); |
| 133 |
$.fn[pluginName] = function(options) { |
| 134 |
var args = arguments; |
| 135 |
if (options === undefined || typeof options === "object") return this.each(function() { |
| 136 |
if (!$.data(this, "plugin_" + pluginName)) $.data(this, "plugin_" + pluginName, new Plugin(this, options)); |
| 137 |
}); |
| 138 |
else if (typeof options === "string" && options[0] !== "_" && options !== "init") { |
| 139 |
var returns; |
| 140 |
this.each(function() { |
| 141 |
var instance = $.data(this, "plugin_" + pluginName); |
| 142 |
if (instance instanceof Plugin && typeof instance[options] === "function") returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1)); |
| 143 |
if (options === "destroy") $.data(this, "plugin_" + pluginName, null); |
| 144 |
}); |
| 145 |
return returns !== undefined ? returns : this; |
| 146 |
} |
| 147 |
}; |
| 148 |
})(jQuery, window, document); |
| 149 |
//#endregion |
| 150 |
})(); |
| 151 |
|