# HG changeset patch # User Ludovic Chabant # Date 1365174492 25200 # Node ID a5a3d454eac9a01bef8f28943654d07c3ea093cf # Parent c0cf67362fb120218da537da12f933e748203fbc Updated Bootstrap. diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/bootstrap-affix.js --- a/static/bootstrap/js/bootstrap-affix.js Wed Apr 03 23:59:07 2013 -0700 +++ b/static/bootstrap/js/bootstrap-affix.js Fri Apr 05 08:08:12 2013 -0700 @@ -1,5 +1,5 @@ /* ========================================================== - * bootstrap-affix.js v2.2.2 + * bootstrap-affix.js v2.3.1 * http://twitter.github.com/bootstrap/javascript.html#affix * ========================================================== * Copyright 2012 Twitter, Inc. diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/bootstrap-alert.js --- a/static/bootstrap/js/bootstrap-alert.js Wed Apr 03 23:59:07 2013 -0700 +++ b/static/bootstrap/js/bootstrap-alert.js Fri Apr 05 08:08:12 2013 -0700 @@ -1,5 +1,5 @@ /* ========================================================== - * bootstrap-alert.js v2.2.2 + * bootstrap-alert.js v2.3.1 * http://twitter.github.com/bootstrap/javascript.html#alerts * ========================================================== * Copyright 2012 Twitter, Inc. diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/bootstrap-button.js --- a/static/bootstrap/js/bootstrap-button.js Wed Apr 03 23:59:07 2013 -0700 +++ b/static/bootstrap/js/bootstrap-button.js Fri Apr 05 08:08:12 2013 -0700 @@ -1,5 +1,5 @@ /* ============================================================ - * bootstrap-button.js v2.2.2 + * bootstrap-button.js v2.3.1 * http://twitter.github.com/bootstrap/javascript.html#buttons * ============================================================ * Copyright 2012 Twitter, Inc. diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/bootstrap-carousel.js --- a/static/bootstrap/js/bootstrap-carousel.js Wed Apr 03 23:59:07 2013 -0700 +++ b/static/bootstrap/js/bootstrap-carousel.js Fri Apr 05 08:08:12 2013 -0700 @@ -1,5 +1,5 @@ /* ========================================================== - * bootstrap-carousel.js v2.2.2 + * bootstrap-carousel.js v2.3.1 * http://twitter.github.com/bootstrap/javascript.html#carousel * ========================================================== * Copyright 2012 Twitter, Inc. @@ -28,6 +28,7 @@ var Carousel = function (element, options) { this.$element = $(element) + this.$indicators = this.$element.find('.carousel-indicators') this.options = options this.options.pause == 'hover' && this.$element .on('mouseenter', $.proxy(this.pause, this)) @@ -38,19 +39,24 @@ cycle: function (e) { if (!e) this.paused = false + if (this.interval) clearInterval(this.interval); this.options.interval && !this.paused && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) return this } + , getActiveIndex: function () { + this.$active = this.$element.find('.item.active') + this.$items = this.$active.parent().children() + return this.$items.index(this.$active) + } + , to: function (pos) { - var $active = this.$element.find('.item.active') - , children = $active.parent().children() - , activePos = children.index($active) + var activeIndex = this.getActiveIndex() , that = this - if (pos > (children.length - 1) || pos < 0) return + if (pos > (this.$items.length - 1) || pos < 0) return if (this.sliding) { return this.$element.one('slid', function () { @@ -58,18 +64,18 @@ }) } - if (activePos == pos) { + if (activeIndex == pos) { return this.pause().cycle() } - return this.slide(pos > activePos ? 'next' : 'prev', $(children[pos])) + return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) } , pause: function (e) { if (!e) this.paused = true if (this.$element.find('.next, .prev').length && $.support.transition.end) { this.$element.trigger($.support.transition.end) - this.cycle() + this.cycle(true) } clearInterval(this.interval) this.interval = null @@ -103,10 +109,19 @@ e = $.Event('slide', { relatedTarget: $next[0] + , direction: direction }) if ($next.hasClass('active')) return + if (this.$indicators.length) { + this.$indicators.find('.active').removeClass('active') + this.$element.one('slid', function () { + var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) + $nextIndicator && $nextIndicator.addClass('active') + }) + } + if ($.support.transition && this.$element.hasClass('slide')) { this.$element.trigger(e) if (e.isDefaultPrevented()) return @@ -151,7 +166,7 @@ if (!data) $this.data('carousel', (data = new Carousel(this, options))) if (typeof option == 'number') data.to(option) else if (action) data[action]() - else if (options.interval) data.cycle() + else if (options.interval) data.pause().cycle() }) } @@ -174,11 +189,18 @@ /* CAROUSEL DATA-API * ================= */ - $(document).on('click.carousel.data-api', '[data-slide]', function (e) { + $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { var $this = $(this), href , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 , options = $.extend({}, $target.data(), $this.data()) + , slideIndex + $target.carousel(options) + + if (slideIndex = $this.attr('data-slide-to')) { + $target.data('carousel').pause().to(slideIndex).cycle() + } + e.preventDefault() }) diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/bootstrap-collapse.js --- a/static/bootstrap/js/bootstrap-collapse.js Wed Apr 03 23:59:07 2013 -0700 +++ b/static/bootstrap/js/bootstrap-collapse.js Fri Apr 05 08:08:12 2013 -0700 @@ -1,5 +1,5 @@ /* ============================================================= - * bootstrap-collapse.js v2.2.2 + * bootstrap-collapse.js v2.3.1 * http://twitter.github.com/bootstrap/javascript.html#collapse * ============================================================= * Copyright 2012 Twitter, Inc. @@ -52,7 +52,7 @@ , actives , hasData - if (this.transitioning) return + if (this.transitioning || this.$element.hasClass('in')) return dimension = this.dimension() scroll = $.camelCase(['scroll', dimension].join('-')) @@ -72,7 +72,7 @@ , hide: function () { var dimension - if (this.transitioning) return + if (this.transitioning || !this.$element.hasClass('in')) return dimension = this.dimension() this.reset(this.$element[dimension]()) this.transition('removeClass', $.Event('hide'), 'hidden') @@ -129,7 +129,7 @@ return this.each(function () { var $this = $(this) , data = $this.data('collapse') - , options = typeof option == 'object' && option + , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option) if (!data) $this.data('collapse', (data = new Collapse(this, options))) if (typeof option == 'string') data[option]() }) diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/bootstrap-dropdown.js --- a/static/bootstrap/js/bootstrap-dropdown.js Wed Apr 03 23:59:07 2013 -0700 +++ b/static/bootstrap/js/bootstrap-dropdown.js Fri Apr 05 08:08:12 2013 -0700 @@ -1,5 +1,5 @@ /* ============================================================ - * bootstrap-dropdown.js v2.2.2 + * bootstrap-dropdown.js v2.3.1 * http://twitter.github.com/bootstrap/javascript.html#dropdowns * ============================================================ * Copyright 2012 Twitter, Inc. @@ -81,7 +81,10 @@ isActive = $parent.hasClass('open') - if (!isActive || (isActive && e.keyCode == 27)) return $this.click() + if (!isActive || (isActive && e.keyCode == 27)) { + if (e.which == 27) $parent.find(toggle).focus() + return $this.click() + } $items = $('[role=menu] li:not(.divider):visible a', $parent) @@ -115,8 +118,9 @@ selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 } - $parent = $(selector) - $parent.length || ($parent = $this.parent()) + $parent = selector && $(selector) + + if (!$parent || !$parent.length) $parent = $this.parent() return $parent } @@ -152,10 +156,10 @@ * =================================== */ $(document) - .on('click.dropdown.data-api touchstart.dropdown.data-api', clearMenus) - .on('click.dropdown touchstart.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) - .on('touchstart.dropdown.data-api', '.dropdown-menu', function (e) { e.stopPropagation() }) - .on('click.dropdown.data-api touchstart.dropdown.data-api' , toggle, Dropdown.prototype.toggle) - .on('keydown.dropdown.data-api touchstart.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown) + .on('click.dropdown.data-api', clearMenus) + .on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) + .on('click.dropdown-menu', function (e) { e.stopPropagation() }) + .on('click.dropdown.data-api' , toggle, Dropdown.prototype.toggle) + .on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown) -}(window.jQuery); \ No newline at end of file +}(window.jQuery); diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/bootstrap-modal.js --- a/static/bootstrap/js/bootstrap-modal.js Wed Apr 03 23:59:07 2013 -0700 +++ b/static/bootstrap/js/bootstrap-modal.js Fri Apr 05 08:08:12 2013 -0700 @@ -1,5 +1,5 @@ /* ========================================================= - * bootstrap-modal.js v2.2.2 + * bootstrap-modal.js v2.3.1 * http://twitter.github.com/bootstrap/javascript.html#modals * ========================================================= * Copyright 2012 Twitter, Inc. @@ -60,8 +60,7 @@ that.$element.appendTo(document.body) //don't move modals dom position } - that.$element - .show() + that.$element.show() if (transition) { that.$element[0].offsetWidth // force reflow @@ -139,16 +138,17 @@ }) } - , hideModal: function (that) { - this.$element - .hide() - .trigger('hidden') - - this.backdrop() + , hideModal: function () { + var that = this + this.$element.hide() + this.backdrop(function () { + that.removeBackdrop() + that.$element.trigger('hidden') + }) } , removeBackdrop: function () { - this.$backdrop.remove() + this.$backdrop && this.$backdrop.remove() this.$backdrop = null } @@ -172,6 +172,8 @@ this.$backdrop.addClass('in') + if (!callback) return + doAnimate ? this.$backdrop.one($.support.transition.end, callback) : callback() @@ -180,8 +182,8 @@ this.$backdrop.removeClass('in') $.support.transition && this.$element.hasClass('fade')? - this.$backdrop.one($.support.transition.end, $.proxy(this.removeBackdrop, this)) : - this.removeBackdrop() + this.$backdrop.one($.support.transition.end, callback) : + callback() } else if (callback) { callback() diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/bootstrap-popover.js --- a/static/bootstrap/js/bootstrap-popover.js Wed Apr 03 23:59:07 2013 -0700 +++ b/static/bootstrap/js/bootstrap-popover.js Fri Apr 05 08:08:12 2013 -0700 @@ -1,5 +1,5 @@ /* =========================================================== - * bootstrap-popover.js v2.2.2 + * bootstrap-popover.js v2.3.1 * http://twitter.github.com/bootstrap/javascript.html#popovers * =========================================================== * Copyright 2012 Twitter, Inc. @@ -58,8 +58,8 @@ , $e = this.$element , o = this.options - content = $e.attr('data-content') - || (typeof o.content == 'function' ? o.content.call($e[0]) : o.content) + content = (typeof o.content == 'function' ? o.content.call($e[0]) : o.content) + || $e.attr('data-content') return content } @@ -99,7 +99,7 @@ placement: 'right' , trigger: 'click' , content: '' - , template: '

' + , template: '

' }) @@ -111,4 +111,4 @@ return this } -}(window.jQuery); \ No newline at end of file +}(window.jQuery); diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/bootstrap-scrollspy.js --- a/static/bootstrap/js/bootstrap-scrollspy.js Wed Apr 03 23:59:07 2013 -0700 +++ b/static/bootstrap/js/bootstrap-scrollspy.js Fri Apr 05 08:08:12 2013 -0700 @@ -1,5 +1,5 @@ /* ============================================================= - * bootstrap-scrollspy.js v2.2.2 + * bootstrap-scrollspy.js v2.3.1 * http://twitter.github.com/bootstrap/javascript.html#scrollspy * ============================================================= * Copyright 2012 Twitter, Inc. @@ -59,7 +59,7 @@ , $href = /^#\w/.test(href) && $(href) return ( $href && $href.length - && [[ $href.position().top + self.$scrollElement.scrollTop(), href ]] ) || null + && [[ $href.position().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]] ) || null }) .sort(function (a, b) { return a[0] - b[0] }) .each(function () { diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/bootstrap-tab.js --- a/static/bootstrap/js/bootstrap-tab.js Wed Apr 03 23:59:07 2013 -0700 +++ b/static/bootstrap/js/bootstrap-tab.js Fri Apr 05 08:08:12 2013 -0700 @@ -1,5 +1,5 @@ /* ======================================================== - * bootstrap-tab.js v2.2.2 + * bootstrap-tab.js v2.3.1 * http://twitter.github.com/bootstrap/javascript.html#tabs * ======================================================== * Copyright 2012 Twitter, Inc. diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/bootstrap-tooltip.js --- a/static/bootstrap/js/bootstrap-tooltip.js Wed Apr 03 23:59:07 2013 -0700 +++ b/static/bootstrap/js/bootstrap-tooltip.js Fri Apr 05 08:08:12 2013 -0700 @@ -1,5 +1,5 @@ /* =========================================================== - * bootstrap-tooltip.js v2.2.2 + * bootstrap-tooltip.js v2.3.1 * http://twitter.github.com/bootstrap/javascript.html#tooltips * Inspired by the original jQuery.tipsy by Jason Frame * =========================================================== @@ -38,19 +38,27 @@ , init: function (type, element, options) { var eventIn , eventOut + , triggers + , trigger + , i this.type = type this.$element = $(element) this.options = this.getOptions(options) this.enabled = true - if (this.options.trigger == 'click') { - this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) - } else if (this.options.trigger != 'manual') { - eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus' - eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur' - this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) - this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) + triggers = this.options.trigger.split(' ') + + for (i = triggers.length; i--;) { + trigger = triggers[i] + if (trigger == 'click') { + this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) + } else if (trigger != 'manual') { + eventIn = trigger == 'hover' ? 'mouseenter' : 'focus' + eventOut = trigger == 'hover' ? 'mouseleave' : 'blur' + this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) + this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) + } } this.options.selector ? @@ -59,7 +67,7 @@ } , getOptions: function (options) { - options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data()) + options = $.extend({}, $.fn[this.type].defaults, this.$element.data(), options) if (options.delay && typeof options.delay == 'number') { options.delay = { @@ -72,7 +80,15 @@ } , enter: function (e) { - var self = $(e.currentTarget)[this.type](this._options).data(this.type) + var defaults = $.fn[this.type].defaults + , options = {} + , self + + this._options && $.each(this._options, function (key, value) { + if (defaults[key] != value) options[key] = value + }, this) + + self = $(e.currentTarget)[this.type](options).data(this.type) if (!self.options.delay || !self.options.delay.show) return self.show() @@ -97,14 +113,16 @@ , show: function () { var $tip - , inside , pos , actualWidth , actualHeight , placement , tp + , e = $.Event('show') if (this.hasContent() && this.enabled) { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return $tip = this.tip() this.setContent() @@ -116,19 +134,18 @@ this.options.placement.call(this, $tip[0], this.$element[0]) : this.options.placement - inside = /in/.test(placement) - $tip .detach() .css({ top: 0, left: 0, display: 'block' }) - .insertAfter(this.$element) - pos = this.getPosition(inside) + this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) + + pos = this.getPosition() actualWidth = $tip[0].offsetWidth actualHeight = $tip[0].offsetHeight - switch (inside ? placement.split(' ')[1] : placement) { + switch (placement) { case 'bottom': tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2} break @@ -143,13 +160,58 @@ break } - $tip - .offset(tp) - .addClass(placement) - .addClass('in') + this.applyPlacement(tp, placement) + this.$element.trigger('shown') } } + , applyPlacement: function(offset, placement){ + var $tip = this.tip() + , width = $tip[0].offsetWidth + , height = $tip[0].offsetHeight + , actualWidth + , actualHeight + , delta + , replace + + $tip + .offset(offset) + .addClass(placement) + .addClass('in') + + actualWidth = $tip[0].offsetWidth + actualHeight = $tip[0].offsetHeight + + if (placement == 'top' && actualHeight != height) { + offset.top = offset.top + height - actualHeight + replace = true + } + + if (placement == 'bottom' || placement == 'top') { + delta = 0 + + if (offset.left < 0){ + delta = offset.left * -2 + offset.left = 0 + $tip.offset(offset) + actualWidth = $tip[0].offsetWidth + actualHeight = $tip[0].offsetHeight + } + + this.replaceArrow(delta - width + actualWidth, actualWidth, 'left') + } else { + this.replaceArrow(actualHeight - height, actualHeight, 'top') + } + + if (replace) $tip.offset(offset) + } + + , replaceArrow: function(delta, dimension, position){ + this + .arrow() + .css(position, delta ? (50 * (1 - delta / dimension) + "%") : '') + } + , setContent: function () { var $tip = this.tip() , title = this.getTitle() @@ -161,6 +223,10 @@ , hide: function () { var that = this , $tip = this.tip() + , e = $.Event('hide') + + this.$element.trigger(e) + if (e.isDefaultPrevented()) return $tip.removeClass('in') @@ -179,6 +245,8 @@ removeWithAnimation() : $tip.detach() + this.$element.trigger('hidden') + return this } @@ -193,11 +261,12 @@ return this.getTitle() } - , getPosition: function (inside) { - return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), { - width: this.$element[0].offsetWidth - , height: this.$element[0].offsetHeight - }) + , getPosition: function () { + var el = this.$element[0] + return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : { + width: el.offsetWidth + , height: el.offsetHeight + }, this.$element.offset()) } , getTitle: function () { @@ -215,6 +284,10 @@ return this.$tip = this.$tip || $(this.options.template) } + , arrow: function(){ + return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow") + } + , validate: function () { if (!this.$element[0].parentNode) { this.hide() @@ -236,8 +309,8 @@ } , toggle: function (e) { - var self = $(e.currentTarget)[this.type](this._options).data(this.type) - self[self.tip().hasClass('in') ? 'hide' : 'show']() + var self = e ? $(e.currentTarget)[this.type](this._options).data(this.type) : this + self.tip().hasClass('in') ? self.hide() : self.show() } , destroy: function () { @@ -269,10 +342,11 @@ , placement: 'top' , selector: false , template: '
' - , trigger: 'hover' + , trigger: 'hover focus' , title: '' , delay: 0 , html: false + , container: false } @@ -284,4 +358,4 @@ return this } -}(window.jQuery); \ No newline at end of file +}(window.jQuery); diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/bootstrap-transition.js --- a/static/bootstrap/js/bootstrap-transition.js Wed Apr 03 23:59:07 2013 -0700 +++ b/static/bootstrap/js/bootstrap-transition.js Fri Apr 05 08:08:12 2013 -0700 @@ -1,5 +1,5 @@ /* =================================================== - * bootstrap-transition.js v2.2.2 + * bootstrap-transition.js v2.3.1 * http://twitter.github.com/bootstrap/javascript.html#transitions * =================================================== * Copyright 2012 Twitter, Inc. diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/bootstrap-typeahead.js --- a/static/bootstrap/js/bootstrap-typeahead.js Wed Apr 03 23:59:07 2013 -0700 +++ b/static/bootstrap/js/bootstrap-typeahead.js Fri Apr 05 08:08:12 2013 -0700 @@ -1,5 +1,5 @@ /* ============================================================= - * bootstrap-typeahead.js v2.2.2 + * bootstrap-typeahead.js v2.3.1 * http://twitter.github.com/bootstrap/javascript.html#typeahead * ============================================================= * Copyright 2012 Twitter, Inc. @@ -172,6 +172,7 @@ , listen: function () { this.$element + .on('focus', $.proxy(this.focus, this)) .on('blur', $.proxy(this.blur, this)) .on('keypress', $.proxy(this.keypress, this)) .on('keyup', $.proxy(this.keyup, this)) @@ -183,6 +184,7 @@ this.$menu .on('click', $.proxy(this.click, this)) .on('mouseenter', 'li', $.proxy(this.mouseenter, this)) + .on('mouseleave', 'li', $.proxy(this.mouseleave, this)) } , eventSupported: function(eventName) { @@ -256,22 +258,33 @@ e.preventDefault() } + , focus: function (e) { + this.focused = true + } + , blur: function (e) { - var that = this - setTimeout(function () { that.hide() }, 150) + this.focused = false + if (!this.mousedover && this.shown) this.hide() } , click: function (e) { e.stopPropagation() e.preventDefault() this.select() + this.$element.focus() } , mouseenter: function (e) { + this.mousedover = true this.$menu.find('.active').removeClass('active') $(e.currentTarget).addClass('active') } + , mouseleave: function (e) { + this.mousedover = false + if (!this.focused && this.shown) this.hide() + } + } @@ -316,7 +329,6 @@ $(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) { var $this = $(this) if ($this.data('typeahead')) return - e.preventDefault() $this.typeahead($this.data()) }) diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/tests/index.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/static/bootstrap/js/tests/index.html Fri Apr 05 08:08:12 2013 -0700 @@ -0,0 +1,56 @@ + + + + Bootstrap Plugin Test Suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Bootstrap Plugin Test Suite

+

+

+
    +
    +
    + + \ No newline at end of file diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/tests/phantom.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/static/bootstrap/js/tests/phantom.js Fri Apr 05 08:08:12 2013 -0700 @@ -0,0 +1,63 @@ +// Simple phantom.js integration script +// Adapted from Modernizr + +function waitFor(testFx, onReady, timeOutMillis) { + var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 5001 //< Default Max Timout is 5s + , start = new Date().getTime() + , condition = false + , interval = setInterval(function () { + if ((new Date().getTime() - start < maxtimeOutMillis) && !condition) { + // If not time-out yet and condition not yet fulfilled + condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()) //< defensive code + } else { + if (!condition) { + // If condition still not fulfilled (timeout but condition is 'false') + console.log("'waitFor()' timeout") + phantom.exit(1) + } else { + // Condition fulfilled (timeout and/or condition is 'true') + typeof(onReady) === "string" ? eval(onReady) : onReady() //< Do what it's supposed to do once the condition is fulfilled + clearInterval(interval) //< Stop this interval + } + } + }, 100) //< repeat check every 100ms +} + + +if (phantom.args.length === 0 || phantom.args.length > 2) { + console.log('Usage: phantom.js URL') + phantom.exit() +} + +var page = new WebPage() + +// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this") +page.onConsoleMessage = function(msg) { + console.log(msg) +}; + +page.open(phantom.args[0], function(status){ + if (status !== "success") { + console.log("Unable to access network") + phantom.exit() + } else { + waitFor(function(){ + return page.evaluate(function(){ + var el = document.getElementById('qunit-testresult') + if (el && el.innerText.match('completed')) { + return true + } + return false + }) + }, function(){ + var failedNum = page.evaluate(function(){ + var el = document.getElementById('qunit-testresult') + try { + return el.getElementsByClassName('failed')[0].innerHTML + } catch (e) { } + return 10000 + }); + phantom.exit((parseInt(failedNum, 10) > 0) ? 1 : 0) + }) + } +}) \ No newline at end of file diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/tests/server.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/static/bootstrap/js/tests/server.js Fri Apr 05 08:08:12 2013 -0700 @@ -0,0 +1,14 @@ +/* + * Simple connect server for phantom.js + * Adapted from Modernizr + */ + +var connect = require('connect') + , http = require('http') + , fs = require('fs') + , app = connect() + .use(connect.static(__dirname + '/../../')); + +http.createServer(app).listen(3000); + +fs.writeFileSync(__dirname + '/pid.txt', process.pid, 'utf-8') \ No newline at end of file diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/tests/unit/bootstrap-affix.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/static/bootstrap/js/tests/unit/bootstrap-affix.js Fri Apr 05 08:08:12 2013 -0700 @@ -0,0 +1,25 @@ +$(function () { + + module("bootstrap-affix") + + test("should provide no conflict", function () { + var affix = $.fn.affix.noConflict() + ok(!$.fn.affix, 'affix was set back to undefined (org value)') + $.fn.affix = affix + }) + + test("should be defined on jquery object", function () { + ok($(document.body).affix, 'affix method is defined') + }) + + test("should return element", function () { + ok($(document.body).affix()[0] == document.body, 'document.body returned') + }) + + test("should exit early if element is not visible", function () { + var $affix = $('
    ').affix() + $affix.data('affix').checkPosition() + ok(!$affix.hasClass('affix'), 'affix class was not added') + }) + +}) \ No newline at end of file diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/tests/unit/bootstrap-alert.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/static/bootstrap/js/tests/unit/bootstrap-alert.js Fri Apr 05 08:08:12 2013 -0700 @@ -0,0 +1,62 @@ +$(function () { + + module("bootstrap-alerts") + + test("should provide no conflict", function () { + var alert = $.fn.alert.noConflict() + ok(!$.fn.alert, 'alert was set back to undefined (org value)') + $.fn.alert = alert + }) + + test("should be defined on jquery object", function () { + ok($(document.body).alert, 'alert method is defined') + }) + + test("should return element", function () { + ok($(document.body).alert()[0] == document.body, 'document.body returned') + }) + + test("should fade element out on clicking .close", function () { + var alertHTML = '
    ' + + '×' + + '

    Holy guacamole! Best check yo self, you\'re not looking too good.

    ' + + '
    ' + , alert = $(alertHTML).alert() + + alert.find('.close').click() + + ok(!alert.hasClass('in'), 'remove .in class on .close click') + }) + + test("should remove element when clicking .close", function () { + $.support.transition = false + + var alertHTML = '
    ' + + '×' + + '

    Holy guacamole! Best check yo self, you\'re not looking too good.

    ' + + '
    ' + , alert = $(alertHTML).appendTo('#qunit-fixture').alert() + + ok($('#qunit-fixture').find('.alert-message').length, 'element added to dom') + + alert.find('.close').click() + + ok(!$('#qunit-fixture').find('.alert-message').length, 'element removed from dom') + }) + + test("should not fire closed when close is prevented", function () { + $.support.transition = false + stop(); + $('
    ') + .bind('close', function (e) { + e.preventDefault(); + ok(true); + start(); + }) + .bind('closed', function () { + ok(false); + }) + .alert('close') + }) + +}) \ No newline at end of file diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/tests/unit/bootstrap-button.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/static/bootstrap/js/tests/unit/bootstrap-button.js Fri Apr 05 08:08:12 2013 -0700 @@ -0,0 +1,102 @@ +$(function () { + + module("bootstrap-buttons") + + test("should provide no conflict", function () { + var button = $.fn.button.noConflict() + ok(!$.fn.button, 'button was set back to undefined (org value)') + $.fn.button = button + }) + + test("should be defined on jquery object", function () { + ok($(document.body).button, 'button method is defined') + }) + + test("should return element", function () { + ok($(document.body).button()[0] == document.body, 'document.body returned') + }) + + test("should return set state to loading", function () { + var btn = $('') + equals(btn.html(), 'mdo', 'btn text equals mdo') + btn.button('loading') + equals(btn.html(), 'fat', 'btn text equals fat') + stop() + setTimeout(function () { + ok(btn.attr('disabled'), 'btn is disabled') + ok(btn.hasClass('disabled'), 'btn has disabled class') + start() + }, 0) + }) + + test("should return reset state", function () { + var btn = $('') + equals(btn.html(), 'mdo', 'btn text equals mdo') + btn.button('loading') + equals(btn.html(), 'fat', 'btn text equals fat') + stop() + setTimeout(function () { + ok(btn.attr('disabled'), 'btn is disabled') + ok(btn.hasClass('disabled'), 'btn has disabled class') + start() + stop() + }, 0) + btn.button('reset') + equals(btn.html(), 'mdo', 'btn text equals mdo') + setTimeout(function () { + ok(!btn.attr('disabled'), 'btn is not disabled') + ok(!btn.hasClass('disabled'), 'btn does not have disabled class') + start() + }, 0) + }) + + test("should toggle active", function () { + var btn = $('') + ok(!btn.hasClass('active'), 'btn does not have active class') + btn.button('toggle') + ok(btn.hasClass('active'), 'btn has class active') + }) + + test("should toggle active when btn children are clicked", function () { + var btn = $('') + , inner = $('') + btn + .append(inner) + .appendTo($('#qunit-fixture')) + ok(!btn.hasClass('active'), 'btn does not have active class') + inner.click() + ok(btn.hasClass('active'), 'btn has class active') + }) + + test("should toggle active when btn children are clicked within btn-group", function () { + var btngroup = $('
    ') + , btn = $('') + , inner = $('') + btngroup + .append(btn.append(inner)) + .appendTo($('#qunit-fixture')) + ok(!btn.hasClass('active'), 'btn does not have active class') + inner.click() + ok(btn.hasClass('active'), 'btn has class active') + }) + + test("should check for closest matching toggle", function () { + var group = $("
    ") + , btn1 = $("") + , btn2 = $("") + , wrap = $("
    ") + + wrap.append(btn1, btn2) + + group + .append(wrap) + .appendTo($('#qunit-fixture')) + + ok(btn1.hasClass('active'), 'btn1 has active class') + ok(!btn2.hasClass('active'), 'btn2 does not have active class') + btn2.click() + ok(!btn1.hasClass('active'), 'btn1 does not have active class') + ok(btn2.hasClass('active'), 'btn2 has active class') + }) + +}) \ No newline at end of file diff -r c0cf67362fb1 -r a5a3d454eac9 static/bootstrap/js/tests/unit/bootstrap-carousel.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/static/bootstrap/js/tests/unit/bootstrap-carousel.js Fri Apr 05 08:08:12 2013 -0700 @@ -0,0 +1,81 @@ +$(function () { + + module("bootstrap-carousel") + + test("should provide no conflict", function () { + var carousel = $.fn.carousel.noConflict() + ok(!$.fn.carousel, 'carousel was set back to undefined (org value)') + $.fn.carousel = carousel + }) + + test("should be defined on jquery object", function () { + ok($(document.body).carousel, 'carousel method is defined') + }) + + test("should return element", function () { + ok($(document.body).carousel()[0] == document.body, 'document.body returned') + }) + + test("should not fire sliden when slide is prevented", function () { + $.support.transition = false + stop() + $('