UNPKG

shut

Version:
519 lines (406 loc) 15.4 kB
(function($) { if (!$.Sh) { $.Sh = {}; }; $.Sh.Expands = function(options) { // a bridge, set up options from data- var _options = { onInit: $.getFunction(this, "oninit"), onShow: $.getFunction(this, "onshow"), onHide: $.getFunction(this, "onhide"), onToggle: $.getFunction(this, "ontoggle"), onBeforeShow: $.getFunction(this, "onbeforeshow"), onBeforeHide: $.getFunction(this, "onbeforehide"), guts: this.data("guts"), src: this.data("hsrc"), state: this.data("state"), active: this.data("active"), effect: this.data("effect"), togglecss: this.data("toggle-css"), hidesrc: this.data("hide-src"), showsrc: this.data("show-src"), keepDefault: this.data("keep-default") // keep default event without prevention }; this.ShExpands($.extend(_options, options)); return this.data("sh.expands"); }; // expose default options $.Sh.Expands.defaults = { guts: '>.guts', src: '>.h', active: true, effect: "slide", togglecss: "toggle", keepDefault: false }; // constructor, not exposed var Expands = function(el, options) { this.element = el; // extend options this.options = $.extend({}, $.Sh.Expands.defaults, options); this.srcElement = el.find(this.options.src); this.gutsElement = el.find(this.options.guts); // initialize this.init(); }; Expands.prototype = { // TODO: change src and guts on runtime init: function() { var base = this; this.srcElement.length && this.element.on("click", base.options.src, function(e) { base._click(e); }); this.options.hidesrc && this.element.on("click", base.options.hidesrc, function(e) { base._click(e, "hide"); }); this.options.showsrc && this.element.on("click", base.options.showsrc, function(e) { base._click(e, "show"); }); base.options.onInit && base.options.onInit.call(this); // if to show show by default if (base.options.state == "show") { base.show(); } else { base.hide(); } // return instance return this; }, addtrigger: function(trigger, verb) { // add trigger on runtime from anywhere var base = this; trigger.on("click", function(e) { base._click(e, verb); }); }, addguts: function(element) { // add element as a new gut? this.gutsElement.add(element); }, _click: function(e, verb) { var base = this; if (!base.options.keepDefault) e.preventDefault(); if (!base.options.active) return; if (verb == "hide") { base.hide(); return; } if (verb == "show") { base.show(); return; } // normally, toggle base.toggle(); }, show: function() { if (!this.options.active) return; if (this.options.onBeforeShow && !this.options.onBeforeShow.call(this)) return this.element; //if (this.options.onBeforeShow) { // this.options.onBeforeShow(); // return this; //} // show , if onToggle is defined, i should find out whether to call it or not according to what? visible state this.options.state = "show"; if (!this.gutsElement.is(":visible")) { this.options.onToggle && this.options.onToggle.call(this); // fire toggle switch (this.options.effect) { case "slide": this.gutsElement.slideDown("fast"); // show break; case "fade": this.gutsElement.fadeIn(); break; case "none": this.gutsElement.show(); break; } } // i think i should return if element is already visibt this.element.addClass(this.options.togglecss); this.options.onShow && this.options.onShow.call(this); // fire onshow anyway // double check return this.element; }, toggle: function() { if (!this.options.active) return; // for effects of slide and fade if (this.gutsElement.is(":visible")) { this.hide(); } else { this.show(); } return this.element; }, hide: function() { if (!this.options.active) return; if (this.options.onBeforeHide && !this.options.onBeforeHide.call(this)) return this; //if (this.options.onBeforeHide) { // this.options.onBeforeHide.call(this); // return this; //} this.options.state = null; if (this.gutsElement.is(":visible")) { this.options.onToggle && this.options.onToggle.call(this); // fire toggle, this shouldnt fire always switch (this.options.effect) { case "slide": this.gutsElement.slideUp("fast"); break; case "fade": this.gutsElement.fadeOut(); break; case "none": this.gutsElement.hide(); break; } } this.element.removeClass(this.options.togglecss); this.options.onHide && this.options.onHide.call(this); return this.element; }, setActive: function(bActive) { this.options.active = bActive; } }; // plugin $.fn.ShExpands = function(options) { return this.each(function() { if (!$(this).data("sh.expands")) { $(this).data("sh.expands", new Expands($(this), options)); } }); }; $.Sh.AltExpands = function() { // on click to show hide src, show guts, on hide, show src $.Sh.Expands.call(this, { onShow: function() { this.srcElement.hide(); }, onHide: function() { this.srcElement.show(); } }); }; $.Sh.ExpandOnce = function() { $.Sh.Expands.call(this, { effect: "none", onShow: function() { this.srcElement.remove(); } }); }; $.Sh.PopList = function(options) { // click element to show hide a well position absolute layer // Feb 23, make this optional var _options = { onShow: this.data('do-position') && function() { // position this.gutsElement.position({ of: this.srcElement, my: "center top", at: "center bottom", collision: "fit fit" // watch this }); } }; var o = $.Sh.Expands.call(this, $.extend(_options, options)); this.data("ondocumentclick", function(e) { if (!jQuery.contains(this.get(0), e.target)) { o.hide(); } }); $.popbasket.push(this); return o; }; $.Sh.ExpandLabel = function(options) { // onshow or hide, change srcelemnet according to passed attributes var slabel, hlabel; var _thisoptions = { mono: this.data("mono"), listsize: this.data("list-size"), gutscss: this.data("guts-css"), selector: this.data("selector"), slabel: this.data("show-label"), hlabel: this.data("hide-label") } _thisoptions = $.extend({}, $.Sh.ExpandLabel.defaults, _thisoptions, options); if (_thisoptions.mono) { this.find(_thisoptions.selector + ":gt(" + (_thisoptions.listsize - 1) + ")").addClass(_thisoptions.gutscss); } // reset options var _options = { onInit: function() { (this.options.state == "show") ? this.srcElement.html(_thisoptions.hlabel): this.srcElement.html(_thisoptions.slabel); if (this.gutsElement.length == 0) this.srcElement.hide(); }, onShow: function() { this.srcElement.html(_thisoptions.hlabel); }, onHide: function() { this.srcElement.html(_thisoptions.slabel); } }; var o = $.Sh.Expands.call(this, $.extend(_options, options)); return o; }; $.Sh.ExpandLabel.defaults = { mono: false, gutscss: "guts", listsize: 3, selector: "li", slabel: $.Res.More, hlabel: $.Res.Less }; $.Sh.FilterList = function(options) { // a bridge, set up options from data- //attach Expands first then use to gather items var o = $.Sh.PopList.call(this, options); var _options = { itemselector: this.data("itemselector"), selected: this.data("selected"), // object selectedValue: this.data("selected-value"), // value css: this.data("css"), onchange: this.data("onchange"), html: this.data("html"), expands: o }; this.ShFilterList($.extend(_options, options)); }; // expose default options $.Sh.FilterList.defaults = { itemselector: "li", css: "selected", html: false }; // constructor, not exposed var FilterList = function(el, options) { // extend options this.options = $.extend({}, $.Sh.FilterList.defaults, options); this.element = el; this.expands = this.options.expands; // inherits expands this.items = this.expands.gutsElement.find(this.options.itemselector); // if no selected, find selected if (!this.options.selected) { // find selected by value or by selected css this.options.selected = this.options.selectedValue ? this.items.filter("[data-value='{0}']".format(this.options.selectedValue)) : this.items.filter("." + this.options.css).first(); // still not found, get first if (!this.options.selected.length) this.options.selected = this.items.first(); } // initialize this.init(options); }; FilterList.prototype = { init: function(options) { var base = this; // update src element with selected element this.expands.gutsElement.on("click", this.options.itemselector, function(e) { base._click(e, $(this)); }); // select selected item this.select(this.options.selected); }, _click: function(e, src) { // change selected if (!this.options.selected.is(src)) { this.items.removeClass(this.options.css); this.select(src); this.options.onchange && this.options.onchange.call(this, src); } //hide this.expands.hide(); //e.preventDefault(); }, additem: function(item) { $.merge(this.options.items, item); }, select: function(item) { item.addClass(this.options.css); this.options.html ? this.expands.srcElement.html(item.html()) : this.expands.srcElement.text(item.text()); // watch this.options.selected = item; } }; // plugin $.fn.ShFilterList = function(options) { return this.each(function() { if (!$(this).data("sh.filterlist")) { $(this).data("sh.filterlist", new FilterList($(this), options)); } }); }; // TABS: client tabs $.Sh.Tabs = function(options) { // guts // exapnds, after adding group and guts var _options = { onSelect: $.getFunction(this, "onselect"), onLoad: $.getFunction(this, "onload"), toggle: this.data("toggle"), effect: this.data("effect"), tabSelector: this.data("tabs"), selectcss: this.data("selected-css") }; this.ShTabs($.extend(_options, options)); return $(this).data("sh.tabs"); }; // expose default options $.Sh.Tabs.defaults = { delay: false, toggle: false, effect: "slide", selectcss: "selected" }; var Tabs = function(el, options) { this.element = el; // extend options this.options = $.extend({}, $.Sh.Tabs.defaults, options); this.collection = []; this.group = this.element.find(this.options.tabSelector); // initialize this.init(); }; Tabs.prototype = { init: function() { var base = this; $.each(base.group, function(i, o) { var expands = $.Sh.Expands.call($(o), { effect: base.options.effect }); expands.gutsElement = $($(o).data("guts")); // TODO: context base.collection.push(expands); }); // selected or first item var selected = base.group.filter("." + base.options.selectcss); base.selected = selected.length ? selected.data("sh.expands") : base.group.first().data("sh.expands"); base.group.on("click", function(e) { e.preventDefault(); // select tab base.select($(this).data("sh.expands")); }); // on load may change selected base.options.onLoad && base.options.onLoad.call(base); // select if one is selected base.selected && base.select(base.selected); // return instance return this; }, select: function(item) { // make all unselected and make item selected // fire hide all, then show this var base = this; if (item.options.state == "show" && !base.options.toggle) return; $.each(base.collection, function(i, o) { o.hide(); o.element.removeClass(base.options.selectcss); }); item.show(); item.element.addClass(base.options.selectcss); base.selected = item; base.options.onSelect && base.options.onSelect.call(base); } }; // plugin $.fn.ShTabs = function(options) { return this.each(function() { if (!$(this).data("sh.tabs")) { $(this).data("sh.tabs", new Tabs($(this), options)); } }); }; })(jQuery);