diff --git a/src/octoprint/static/css/bootstrap-tabdrop.css b/src/octoprint/static/css/bootstrap-tabdrop.css new file mode 100644 index 00000000..4ac46813 --- /dev/null +++ b/src/octoprint/static/css/bootstrap-tabdrop.css @@ -0,0 +1,12 @@ +/*! + * Tab drop for Bootstrap + * + * Copyright 2012 Stefan Petre + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ +.nav-tabs, +.nav-pills { + position: relative; +} diff --git a/src/octoprint/static/js/app/main.js b/src/octoprint/static/js/app/main.js index c5bb6f92..342e4f4d 100644 --- a/src/octoprint/static/js/app/main.js +++ b/src/octoprint/static/js/app/main.js @@ -236,8 +236,12 @@ $(function() { return $(window).height() - 165; }; + // Use bootstrap tabdrop for tabs and pills + $('.nav-pills, .nav-tabs').tabdrop(); + // Allow components to react to tab change - $('#tabs a[data-toggle="tab"]').on('show', function (e) { + var tabs = $('#tabs a[data-toggle="tab"]'); + tabs.on('show', function (e) { var current = e.target.hash; var previous = e.relatedTarget.hash; @@ -248,7 +252,7 @@ $(function() { }); }); - $('#tabs a[data-toggle="tab"]').on('shown', function (e) { + tabs.on('shown', function (e) { var current = e.target.hash; var previous = e.relatedTarget.hash; @@ -293,7 +297,7 @@ $(function() { return; } - if (!Array.isArray(targets)) { + if (!_.isArray(targets)) { targets = [targets]; } @@ -318,14 +322,14 @@ $(function() { object = target; } - if (object == undefined) { - log.error("Could not apply binding for view model", viewModel.constructor.name, ": target", target, "does not exist"); + if (object == undefined || !object.length) { + log.info("Did not bind view model", viewModel.constructor.name, "to target", target, "since it does not exist"); return; } var element = object.get(0); if (element == undefined) { - log.error("Could not apply binding for view model", viewModel.constructor.name, ": target", target, "does not exist"); + log.info("Did not bind view model", viewModel.constructor.name, "to target", target, "since it does not exist"); return; } diff --git a/src/octoprint/static/js/lib/bootstrap/bootstrap-tabdrop.js b/src/octoprint/static/js/lib/bootstrap/bootstrap-tabdrop.js new file mode 100644 index 00000000..3546ba97 --- /dev/null +++ b/src/octoprint/static/js/lib/bootstrap/bootstrap-tabdrop.js @@ -0,0 +1,117 @@ +/* ========================================================= + * bootstrap-tabdrop.js + * http://www.eyecon.ro/bootstrap-tabdrop + * ========================================================= + * Copyright 2012 Stefan Petre + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================= */ + +!function( $ ) { + + var WinReszier = (function(){ + var registered = []; + var inited = false; + var timer; + var resize = function(ev) { + clearTimeout(timer); + timer = setTimeout(notify, 100); + }; + var notify = function() { + for(var i=0, cnt=registered.length; i'+options.text+' ') + .prependTo(this.element); + if (this.element.parent().is('.tabs-below')) { + this.dropdown.addClass('dropup'); + } + WinReszier.register($.proxy(this.layout, this)); + this.layout(); + }; + + TabDrop.prototype = { + constructor: TabDrop, + + layout: function() { + var collection = []; + this.dropdown.removeClass('hide'); + this.element + .append(this.dropdown.find('li')) + .find('>li') + .not('.tabdrop') + .each(function(){ + if(this.offsetTop > 0) { + collection.push(this); + } + }); + if (collection.length > 0) { + collection = $(collection); + this.dropdown + .find('ul') + .empty() + .append(collection); + if (this.dropdown.find('.active').length == 1) { + this.dropdown.addClass('active'); + } else { + this.dropdown.removeClass('active'); + } + } else { + this.dropdown.addClass('hide'); + } + } + } + + $.fn.tabdrop = function ( option ) { + return this.each(function () { + var $this = $(this), + data = $this.data('tabdrop'), + options = typeof option === 'object' && option; + if (!data) { + $this.data('tabdrop', (data = new TabDrop(this, $.extend({}, $.fn.tabdrop.defaults,options)))); + } + if (typeof option == 'string') { + data[option](); + } + }) + }; + + $.fn.tabdrop.defaults = { + text: '' + }; + + $.fn.tabdrop.Constructor = TabDrop; + +}( window.jQuery ); \ No newline at end of file