/* * Side navigation tree * * Data attributes: * - data-control="sidenav-tree" - enables the plugin * - data-tree-name - unique name of the tree control. The name is used for storing user configuration in the browser cookies. * * JavaScript API: * $('#tree').sidenavTree() * * Dependences: * - Null */ +function ($) { "use strict"; // SIDENAVTREE CLASS DEFINITION // ============================ var SidenavTree = function(element, options) { this.options = options this.$el = $(element) this.init() } SidenavTree.DEFAULTS = { treeName: 'sidenav_tree' } SidenavTree.prototype.init = function (){ var self = this $(document.body).addClass('has-sidenav-tree') this.statusCookieName = this.options.treeName + 'groupStatus' this.searchCookieName = this.options.treeName + 'search' this.$searchInput = $(this.options.searchInput) this.$el.on('click', 'li > div.group', function() { self.toggleGroup($(this).closest('li')) return false }) this.$searchInput.on('input', function(){ self.handleSearchChange() }) var searchTerm = $.cookie(this.searchCookieName) if (searchTerm !== undefined && searchTerm.length > 0) { this.$searchInput.val(searchTerm) this.applySearch() } var scrollbar = $('[data-control=scrollbar]', this.$el).data('oc.scrollbar'), active = $('li.active', this.$el) if (active.length > 0) { scrollbar.gotoElement(active) } } SidenavTree.prototype.toggleGroup = function(group) { var $group = $(group), status = $group.attr('data-status') status === undefined || status == 'expanded' ? this.collapseGroup($group) : this.expandGroup($group) } SidenavTree.prototype.collapseGroup = function(group) { var $list = $('> ul', group), self = this $list.css('overflow', 'hidden') $list.animate({ 'height': 0 }, { duration: 100, queue: false, complete: function() { $list.css({ 'overflow': 'visible', 'display': 'none' }) $(group).attr('data-status', 'collapsed') $(window).trigger('oc.updateUi') self.saveGroupStatus($(group).data('group-code'), true) } }) } SidenavTree.prototype.expandGroup = function(group, duration) { var $list = $('> ul', group), self = this duration = duration === undefined ? 100 : duration $list.css({ 'overflow': 'hidden', 'height': 0 }) $list.animate({'height': $list[0].scrollHeight}, { duration: duration, queue: false, complete: function() { $list.css({ 'overflow': 'visible', 'height': 'auto', 'display': '' }) $(group).attr('data-status', 'expanded') $(window).trigger('oc.updateUi') self.saveGroupStatus($(group).data('group-code'), false) } }) } SidenavTree.prototype.saveGroupStatus = function(groupCode, collapsed) { var collapsedGroups = $.cookie(this.statusCookieName), updatedGroups = [] if (collapsedGroups === undefined) { collapsedGroups = '' } collapsedGroups = collapsedGroups.split('|') $.each(collapsedGroups, function() { if (groupCode != this) updatedGroups.push(this) }) if (collapsed) { updatedGroups.push(groupCode) } $.cookie(this.statusCookieName, updatedGroups.join('|'), { expires: 30, path: '/' }) } SidenavTree.prototype.handleSearchChange = function() { var lastValue = this.$searchInput.data('oc.lastvalue'); if (lastValue !== undefined && lastValue == this.$searchInput.val()) { return } this.$searchInput.data('oc.lastvalue', this.$searchInput.val()) if (this.dataTrackInputTimer !== undefined) { window.clearTimeout(this.dataTrackInputTimer) } var self = this this.dataTrackInputTimer = window.setTimeout(function(){ self.applySearch() }, 300); $.cookie(this.searchCookieName, $.trim(this.$searchInput.val()), { expires: 30, path: '/' }) } SidenavTree.prototype.applySearch = function() { var query = $.trim(this.$searchInput.val()), words = query.toLowerCase().split(' '), visibleGroups = [], visibleItems = [], self = this if (query.length == 0) { $('li', this.$el).removeClass('hidden') return } /* * Find visible groups and items */ $('ul.top-level > li', this.$el).each(function() { var $li = $(this) if (self.textContainsWords($('div.group h3', $li).text(), words)) { visibleGroups.push($li.get(0)) $('ul li', $li).each(function(){ visibleItems.push(this) }) } else { $('ul li', $li).each(function(){ if (self.textContainsWords($(this).text(), words) || self.textContainsWords($(this).data('keywords'), words)) { visibleGroups.push($li.get(0)) visibleItems.push(this) } }) } }) /* * Hide invisible groups and items */ $('ul.top-level > li', this.$el).each(function() { var $li = $(this), groupIsVisible = $.inArray(this, visibleGroups) !== -1 $li.toggleClass('hidden', !groupIsVisible) if (groupIsVisible) self.expandGroup($li, 0) $('ul li', $li).each(function(){ var $itemLi = $(this) $itemLi.toggleClass('hidden', $.inArray(this, visibleItems) == -1) }) }) return false } SidenavTree.prototype.textContainsWords = function(text, words) { text = text.toLowerCase() for (var i = 0; i < words.length; i++) { if (text.indexOf(words[i]) === -1) return false } return true } // SIDENAVTREE PLUGIN DEFINITION // ============================ var old = $.fn.sidenavTree $.fn.sidenavTree = function (option) { var args = arguments; return this.each(function () { var $this = $(this) var data = $this.data('oc.sidenavTree') var options = $.extend({}, SidenavTree.DEFAULTS, $this.data(), typeof option == 'object' && option) if (!data) $this.data('oc.sidenavTree', (data = new SidenavTree(this, options))) if (typeof option == 'string') { var methodArgs = []; for (var i=1; i