aboutsummaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
authorMark Otto <[email protected]>2011-11-29 22:35:58 -0800
committerMark Otto <[email protected]>2011-11-29 22:35:58 -0800
commitcbb291b8ab316c3c0103da3c7b7a2c73596cfef2 (patch)
treee632dc37d1f3dda4e91a06d4f671313a7e476187 /js
parentb36df463108e2e4df8c389a06f577823564788d9 (diff)
parent08d0aff19f8ad8fa2a9cfa389b8753c4525ea99c (diff)
downloadbootstrap-cbb291b8ab316c3c0103da3c7b7a2c73596cfef2.tar.xz
bootstrap-cbb291b8ab316c3c0103da3c7b7a2c73596cfef2.zip
Merge branch '2.0-wip' of github.com:twitter/bootstrap into 2.0-wip
Conflicts: bootstrap.css bootstrap.min.css
Diffstat (limited to 'js')
-rw-r--r--js/README.md88
-rw-r--r--js/bootstrap-accordion.js41
-rw-r--r--js/bootstrap-alert.js76
-rw-r--r--js/bootstrap-alerts.js48
-rw-r--r--js/bootstrap-button.js96
-rw-r--r--js/bootstrap-collapse.js133
-rw-r--r--js/bootstrap-dropdown.js53
-rw-r--r--js/bootstrap-modal.js199
-rw-r--r--js/bootstrap-popover.js30
-rw-r--r--js/bootstrap-scrollspy.js61
-rw-r--r--js/bootstrap-tab.js102
-rw-r--r--js/bootstrap-tabs.js71
-rw-r--r--js/bootstrap-transition.js (renamed from js/bootstrap-transitions.js)2
-rw-r--r--js/bootstrap-twipsy.js86
14 files changed, 745 insertions, 341 deletions
diff --git a/js/README.md b/js/README.md
new file mode 100644
index 000000000..2eef9e735
--- /dev/null
+++ b/js/README.md
@@ -0,0 +1,88 @@
+## 2.0 BOOTSTRAP JS PHILOSOPHY
+These are the high-level design rules which guide the development of Bootstrap's JS plugins.
+
+---
+
+### DATA-ATTRIBUTE API
+
+We believe you should be able to use all plugins provided by Bootstrap purely through the markup API without writing a single line of javascript.
+
+We acknowledge that this isn't always the most performant and sometimes it may be desirable to turn this functionality off altogether. Therefore, as of 2.0 we provide the ability to disable the data attribute API by unbinding all events on the body namespaced with `'data-api'`. This looks like this:
+
+ $('body').unbind('.data-api')
+
+To target a specific plugin, just include the plugins name as a namespace along with the data-api namespace like this:
+
+ $('body').unbind('.alert.data-api')
+
+---
+
+### PROGRAMATIC API
+
+We also believe you should be able to use all plugins provided by Bootstrap purely through the JS API.
+
+All public APIs should be a single, chainable method, and return the collection acted upon.
+
+ $(".btn.danger").button("toggle").addClass("fat")
+
+All methods should accept an optional options object, a string which targets a particular method, or null which initiates the default behavior:
+
+ $("#myModal").modal() // initialized with defaults
+
+---
+
+### PLUGIN OPTIONS
+
+Options should be sparse and add universal value. We should pick the right defaults.
+
+All plugins should have a default object which can be modified to effect all instance's default options. The defaults object should be available via `$.fn.plugin.defaults`.
+
+ $.fn.modal.defaults = { … }
+
+An options definition should take the following form:
+
+ *noun*: *adjective* - describes or modifies a quality of an instance
+
+examples:
+
+ backdrop: true
+ keyboard: false
+ placement: 'above'
+
+---
+
+### PLUGIN EVENTS
+
+All events should have an infinitive and past participle form. The infinitive is fired just before an action takes place, the past participle on completion of the action.
+
+ show | shown
+ hide | hidden
+
+---
+
+
+### DATA ATTRIBUTES
+
+Data attributes should take the following form:
+
+- data-*(verb)* - defines main interaction
+- data-target || href^=# - defined on controller element (if element interacts with an element other than self)
+- data-*(noun)* - defines options for element invocation
+
+examples:
+
+ // control other targets
+ data-toggle="modal" data-target="#foo"
+ data-toggle="collapse" data-target="#foo" data-parent="#foo"
+
+ // defined on element they control
+ data-spy="scroll"
+
+ data-dismiss="modal"
+ data-dismiss="alert"
+
+ data-toggle="dropdown"
+
+ data-toggle="button"
+ data-toggle="buttons-checkbox"
+ data-toggle="buttons-radio" \ No newline at end of file
diff --git a/js/bootstrap-accordion.js b/js/bootstrap-accordion.js
deleted file mode 100644
index 9a24b5ddf..000000000
--- a/js/bootstrap-accordion.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/* =============================================================
- * bootstrap-accordion.js v2.0.0
- * http://twitter.github.com/bootstrap/javascript.html#accordion
- * =============================================================
- * Copyright 2011 Twitter, Inc.
- *
- * 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 Accordion = function ( element, options ) {}
-
- Accordion.prototype = {}
-
- /* ALERT PLUGIN DEFINITION
- * ======================= */
-
- $.fn.accordion = function ( options ) {
-
- if ( options === true ) {
- return this.data('accordion')
- }
-
- return this.each(function () {
- new Accordion(this, options)
- })
- }
-
-
-})( window.jQuery || window.ender ) \ No newline at end of file
diff --git a/js/bootstrap-alert.js b/js/bootstrap-alert.js
new file mode 100644
index 000000000..210512a8b
--- /dev/null
+++ b/js/bootstrap-alert.js
@@ -0,0 +1,76 @@
+/* ==========================================================
+ * bootstrap-alert.js v2.0.0
+ * http://twitter.github.com/bootstrap/javascript.html#alerts
+ * ==========================================================
+ * Copyright 2011 Twitter, Inc.
+ *
+ * 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( $ ){
+
+ "use strict"
+
+ /* ALERT CLASS DEFINITION
+ * ====================== */
+
+ var dismiss = '[data-dismiss="alert"]'
+ , Alert = function ( el ) {
+ $(el).delegate(dismiss, 'click', this.close)
+ }
+
+ Alert.prototype = {
+
+ close: function ( e ) {
+ var $element = $(this)
+
+ $element = $element.hasClass('alert-message') ? $element : $element.parent()
+ e && e.preventDefault()
+ $element.removeClass('in')
+
+ function removeElement() {
+ $element.remove()
+ }
+
+ $.support.transition && $element.hasClass('fade') ?
+ $element.bind($.support.transition.end, removeElement) :
+ removeElement()
+ }
+
+ }
+
+
+ /* ALERT PLUGIN DEFINITION
+ * ======================= */
+
+ $.fn.alert = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('alert')
+ if (!data) $this.data('alert', (data = new Alert(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ $.fn.alert.Alert = Alert
+
+
+ /* ALERT DATA-API
+ * ============== */
+
+ $(function () {
+ $('body').delegate(dismiss, 'click.alert.data-api', Alert.prototype.close)
+ })
+
+}( window.jQuery || window.ender ) \ No newline at end of file
diff --git a/js/bootstrap-alerts.js b/js/bootstrap-alerts.js
deleted file mode 100644
index 4f1acfa3d..000000000
--- a/js/bootstrap-alerts.js
+++ /dev/null
@@ -1,48 +0,0 @@
-/* ==========================================================
- * bootstrap-alerts.js v2.0.0
- * http://twitter.github.com/bootstrap/javascript.html#alerts
- * ==========================================================
- * Copyright 2011 Twitter, Inc.
- *
- * 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( $ ){
-
- /* ALERT CLASS DEFINITION
- * ====================== */
-
- function close(e) {
- var $element = $(this).parent('.alert-message')
-
- e && e.preventDefault()
- $element.removeClass('in')
-
- function removeElement () {
- $element.remove()
- }
-
- $.support.transition && $element.hasClass('fade') ?
- $element.bind($.support.transition.end, removeElement) :
- removeElement()
- }
-
-
- /* ALERT PLUGIN DEFINITION
- * ======================= */
-
- $(function () {
- $('body').delegate('[data-alert-dismiss]', 'click', close)
- })
-
-})( window.jQuery || window.ender ) \ No newline at end of file
diff --git a/js/bootstrap-button.js b/js/bootstrap-button.js
new file mode 100644
index 000000000..1cafe4d68
--- /dev/null
+++ b/js/bootstrap-button.js
@@ -0,0 +1,96 @@
+/* ============================================================
+ * bootstrap-buttons.js v2.0.0
+ * http://twitter.github.com/bootstrap/javascript.html#buttons
+ * ============================================================
+ * Copyright 2011 Twitter, Inc.
+ *
+ * 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( $ ){
+
+ "use strict"
+
+ /* BUTTON PUBLIC CLASS DEFINITION
+ * ============================== */
+
+ var Button = function (element, options) {
+ this.$element = $(element)
+ this.settings = $.extend({}, $.fn.button.defaults, options)
+ }
+
+ Button.prototype = {
+
+ setState: function (state) {
+ var d = 'disabled'
+ , $el = this.$element
+ , data = $el.data()
+ , val = $el.is('input') ? 'val' : 'html'
+
+ state = state + 'Text'
+ data.resetText || $el.data('resetText', $el[val]())
+
+ $el[val](data[state] || this.settings[state])
+
+ // push to event loop to allow forms to submit
+ setTimeout(function () {
+ state == 'loadingText' ?
+ $el.addClass(d).attr(d, d) :
+ $el.removeClass(d).removeAttr(d)
+ }, 0)
+ }
+
+ , toggle: function () {
+ var $parent = this.$element.parent('[data-toggle="buttons-radio"]')
+
+ $parent && $parent
+ .find('.active')
+ .removeClass('active')
+
+ this.$element.toggleClass('active')
+ }
+
+ }
+
+
+ /* BUTTON PLUGIN DEFINITION
+ * ======================== */
+
+ $.fn.button = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('button')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('button', (data = new Button(this, options)))
+ if (option == 'toggle') data.toggle()
+ else if (option) data.setState(option)
+ })
+ }
+
+ $.fn.button.defaults = {
+ loadingText: 'loading...'
+ }
+
+ $.fn.button.Button = Button
+
+
+ /* BUTTON DATA-API
+ * =============== */
+
+ $(function () {
+ $('body').delegate('[data-toggle^=button]', 'click.button.data-api', function (e) {
+ $(e.srcElement).button('toggle')
+ })
+ })
+
+}( window.jQuery || window.ender ) \ No newline at end of file
diff --git a/js/bootstrap-collapse.js b/js/bootstrap-collapse.js
new file mode 100644
index 000000000..93f91513e
--- /dev/null
+++ b/js/bootstrap-collapse.js
@@ -0,0 +1,133 @@
+/* =============================================================
+ * bootstrap-collapsible.js v2.0.0
+ * http://twitter.github.com/bootstrap/javascript.html#collapsible
+ * =============================================================
+ * Copyright 2011 Twitter, Inc.
+ *
+ * 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( $ ){
+
+ "use strict"
+
+ var Collapse = function ( element, options ) {
+ this.$element = $(element)
+ this.settings = $.extend({}, $.fn.collapse.defaults, options)
+
+ if (this.settings["parent"]) {
+ this.$parent = $(this.settings["parent"])
+ }
+
+ this.settings.toggle && this.toggle()
+ }
+
+ Collapse.prototype = {
+
+ dimension: function () {
+ var hasWidth = this.$element.hasClass('width')
+ return hasWidth ? 'width' : 'height'
+ }
+
+ , show: function () {
+ var dimension = this.dimension()
+ , scroll = $.camelCase(['scroll', dimension].join('-'))
+ , actives = this.$parent && this.$parent.find('.in')
+ , hasData
+
+ if (actives && actives.length) {
+ hasData = actives.data('collapse')
+ actives.collapse('hide')
+ hasData || actives.data('collapse', null)
+ }
+
+ this.$element[dimension](0)
+ this.transition('addClass', 'show', 'shown')
+ this.$element[dimension](this.$element[0][scroll])
+
+ }
+
+ , hide: function () {
+ var dimension = this.dimension()
+ this.reset(this.$element[dimension]())
+ this.transition('removeClass', 'hide', 'hidden')
+ this.$element[dimension](0)
+ }
+
+ , reset: function ( size ) {
+ var dimension = this.dimension()
+
+ this.$element
+ .removeClass('collapse')
+ [dimension](size || '')
+ [0].offsetWidth
+
+ this.$element.addClass('collapse')
+ }
+
+ , transition: function ( method, startEvent, completeEvent ) {
+ var that = this
+ , complete = function () {
+ if (startEvent == 'show') that.reset()
+ that.$element.trigger(completeEvent)
+ }
+
+ this.$element
+ .trigger(startEvent)
+ [method]('in')
+
+ $.support.transition && this.$element.hasClass('collapse') ?
+ this.$element.one($.support.transition.end, complete) :
+ complete()
+ }
+
+ , toggle: function () {
+ this[this.$element.hasClass('in') ? 'hide' : 'show']()
+ }
+
+ }
+
+ /* COLLAPSIBLE PLUGIN DEFINITION
+ * ============================== */
+
+ $.fn.collapse = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('collapse')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('collapse', (data = new Collapse(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.collapse.defaults = {
+ toggle: true
+ }
+
+ $.fn.collapse.Collapse = Collapse
+
+
+ /* COLLAPSIBLE DATA-API
+ * ==================== */
+
+ $(function () {
+ $('body').delegate('[data-toggle=collapse]', 'click.collapse.data-api', function ( e ) {
+ var $this = $(this)
+ , target = $this.attr('data-target') || $this.attr('href')
+ , option = $(target).data('collapse') ? 'toggle' : $this.data()
+ e.preventDefault()
+ $(target).collapse(option)
+ })
+ })
+
+})( window.jQuery || window.ender ) \ No newline at end of file
diff --git a/js/bootstrap-dropdown.js b/js/bootstrap-dropdown.js
index d12fe48cb..7259284bf 100644
--- a/js/bootstrap-dropdown.js
+++ b/js/bootstrap-dropdown.js
@@ -18,25 +18,56 @@
* ============================================================ */
-(function( $ ){
+!function( $ ){
- /* APPLY TO STANDARD DROPDOWN ELEMENTS
- * =================================== */
- var selector = '[data-dropdown]'
+ "use strict"
- function clearMenus() {
- $(selector).parent('li').removeClass('open')
- }
+ /* DROPDOWN CLASS DEFINITION
+ * ========================= */
- $(function () {
- $('html').bind("click", clearMenus)
- $('body').delegate(selector, 'click', function (e) {
+ var toggle = '[data-toggle="dropdown"]'
+ , Dropdown = function ( element ) {
+ $(element).bind('click', this.toggle)
+ }
+
+ Dropdown.prototype = {
+
+ toggle: function ( e ) {
var li = $(this).parent('li')
, isActive = li.hasClass('open')
+
clearMenus()
!isActive && li.toggleClass('open')
+
return false
+ }
+
+ }
+
+ function clearMenus() {
+ $(toggle).parent('li').removeClass('open')
+ }
+
+
+ /* DROPDOWN PLUGIN DEFINITION
+ * ========================== */
+
+ $.fn.dropdown = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('dropdown')
+ if (!data) $this.data('dropdown', (data = new Dropdown(this)))
+ if (typeof option == 'string') data[option].call($this)
})
+ }
+
+
+ /* APPLY TO STANDARD DROPDOWN ELEMENTS
+ * =================================== */
+
+ $(function () {
+ $('html').bind('click.dropdown.data-api', clearMenus)
+ $('body').delegate(toggle, 'click.dropdown.data-api', Dropdown.prototype.toggle)
})
-})( window.jQuery || window.ender ) \ No newline at end of file
+}( window.jQuery || window.ender ) \ No newline at end of file
diff --git a/js/bootstrap-modal.js b/js/bootstrap-modal.js
index 984b091d6..5f543c553 100644
--- a/js/bootstrap-modal.js
+++ b/js/bootstrap-modal.js
@@ -20,19 +20,16 @@
!function( $ ){
- /* MODAL PUBLIC CLASS DEFINITION
- * ============================= */
+ "use strict"
+
+ /* MODAL CLASS DEFINITION
+ * ====================== */
var Modal = function ( content, options ) {
this.settings = $.extend({}, $.fn.modal.defaults, options)
this.$element = $(content)
- .delegate('[data-modal-dismiss]', 'click', $.proxy(this.hide, this))
-
- if ( this.settings.show ) {
- this.show()
- }
-
- return this
+ .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
+ this.settings.show && this.show()
}
Modal.prototype = {
@@ -43,21 +40,37 @@
, show: function () {
var that = this
+
+ if (this.isShown) return
+
this.isShown = true
this.$element.trigger('show')
escape.call(this)
- backdrop.call(this)
+ backdrop.call(this, function () {
+ var transition = $.support.transition && that.$element.hasClass('fade')
- return this
+ that.$element
+ .appendTo(document.body)
+ .show()
+
+ if (transition) {
+ that.$element[0].offsetWidth // force reflow
+ }
+
+ that.$element.addClass('in')
+
+ transition ?
+ that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) :
+ that.$element.trigger('shown')
+
+ })
}
- , hide: function (e) {
+ , hide: function ( e ) {
e && e.preventDefault()
- if ( !this.isShown ) {
- return this
- }
+ if (!this.isShown) return
var that = this
this.isShown = false
@@ -68,19 +81,9 @@
.trigger('hide')
.removeClass('in')
- function removeElement () {
- that.$element
- .hide()
- .trigger('hidden')
-
- backdrop.call(that)
- }
-
$.support.transition && this.$element.hasClass('fade') ?
- this.$element.one($.support.transition.end, removeElement) :
- removeElement()
-
- return this
+ hideWithTransition.call(this) :
+ hideModal.call(this)
}
}
@@ -89,24 +92,42 @@
/* MODAL PRIVATE METHODS
* ===================== */
- function backdrop () {
+ function hideWithTransition() {
+ var that = this
+ , timeout = setTimeout(function () {
+ that.$element.unbind($.support.transition.end)
+ hideModal.call(that)
+ }, 500)
+
+ this.$element.one($.support.transition.end, function () {
+ clearTimeout(timeout)
+ hideModal.call(that)
+ })
+ }
+
+ function hideModal (that) {
+ this.$element
+ .hide()
+ .trigger('hidden')
+
+ backdrop.call(this)
+ }
+
+ function backdrop ( callback ) {
var that = this
, animate = this.$element.hasClass('fade') ? 'fade' : ''
- , callback = $.proxy(show, this)
- if ( this.isShown && this.settings.backdrop ) {
+ if (this.isShown && this.settings.backdrop) {
var doAnimate = $.support.transition && animate
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
.appendTo(document.body)
- if ( this.settings.backdrop != 'static' ) {
+ if (this.settings.backdrop != 'static') {
this.$backdrop.click($.proxy(this.hide, this))
}
- if ( doAnimate ) {
- this.$backdrop[0].offsetWidth // force reflow
- }
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
this.$backdrop.addClass('in')
@@ -114,52 +135,31 @@
this.$backdrop.one($.support.transition.end, callback) :
callback()
- } else if ( !this.isShown && this.$backdrop ) {
+ } else if (!this.isShown && this.$backdrop) {
this.$backdrop.removeClass('in')
- function removeElement() {
- that.$backdrop.remove()
- that.$backdrop = null
- }
-
$.support.transition && this.$element.hasClass('fade')?
- this.$backdrop.one($.support.transition.end, removeElement) :
- removeElement()
- } else if ( callback ) {
- callback()
- }
- }
-
- function show() {
- var transition = $.support.transition && that.$element.hasClass('fade')
- , that = this
+ this.$backdrop.one($.support.transition.end, $.proxy(removeBackdrop, this)) :
+ removeBackdrop.call(this)
- this.$element
- .appendTo(document.body)
- .show()
-
- if (transition) {
- this.$element[0].offsetWidth // force reflow
+ } else if (callback) {
+ callback()
}
+ }
- this.$element
- .addClass('in')
-
- transition ?
- this.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) :
- this.$element.trigger('shown')
+ function removeBackdrop() {
+ this.$backdrop.remove()
+ this.$backdrop = null
}
function escape() {
var that = this
- if ( this.isShown && this.settings.keyboard ) {
- $(document).bind('keyup.modal', function ( e ) {
- if ( e.which == 27 ) {
- that.hide()
- }
+ if (this.isShown && this.settings.keyboard) {
+ $(document).bind('keyup.dismiss.modal', function ( e ) {
+ e.which == 27 && that.hide()
})
- } else if ( !this.isShown ) {
- $(document).unbind('keyup.modal')
+ } else if (!this.isShown) {
+ $(document).unbind('keyup.dismiss.modal')
}
}
@@ -167,53 +167,36 @@
/* MODAL PLUGIN DEFINITION
* ======================= */
- $.fn.modal = function ( options ) {
- var modal = this.data('modal')
-
- if (!modal) {
-
- if (typeof options == 'string') {
- options = {
- show: /show|toggle/.test(options)
- }
- }
-
- return this.each(function () {
- $(this).data('modal', new Modal(this, options))
- })
- }
-
- if ( options === true ) {
- return modal
- }
-
- if ( typeof options == 'string' ) {
- modal[options]()
- } else if ( modal ) {
- modal.toggle()
- }
-
- return this
+ $.fn.modal = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('modal')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('modal', (data = new Modal(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
}
- $.fn.modal.Modal = Modal
-
$.fn.modal.defaults = {
- backdrop: false
- , keyboard: false
- , show: false
+ backdrop: true
+ , keyboard: true
+ , show: true
}
+ $.fn.modal.Modal = Modal
+
- /* MODAL DATA-IMPLEMENTATION
- * ========================= */
+ /* MODAL DATA-API
+ * ============== */
- $(function () {
- $('body').delegate('[data-controls-modal]', 'click', function (e) {
+ $(document).ready(function () {
+ $('body').delegate('[data-toggle="modal"]', 'click.modal.data-api', function ( e ) {
+ var $this = $(this)
+ , target = $this.attr('data-target') || $this.attr('href')
+ , option = $(target).data('modal') ? 'toggle' : $this.data()
e.preventDefault()
- var $this = $(this).data('show', true)
- $('#' + $this.attr('data-controls-modal')).modal( $this.data() )
+ $(target).modal(option)
})
})
-}( window.jQuery || window.ender ); \ No newline at end of file
+}( window.jQuery || window.ender ) \ No newline at end of file
diff --git a/js/bootstrap-popover.js b/js/bootstrap-popover.js
index 3fdde19b5..3c67b18fc 100644
--- a/js/bootstrap-popover.js
+++ b/js/bootstrap-popover.js
@@ -20,6 +20,8 @@
!function( $ ) {
+ "use strict"
+
var Popover = function ( element, options ) {
this.$element = $(element)
this.options = options
@@ -34,34 +36,44 @@
setContent: function () {
var $tip = this.tip()
- $tip.find('.title')[this.options.html ? 'html' : 'text'](this.getTitle())
- $tip.find('.content p')[this.options.html ? 'html' : 'text'](this.getContent())
+ , title = this.getTitle()
+ , content = this.getContent()
+
+ $tip.find('.title')[ $.type(title) == 'object' ? 'append' : 'html' ](title)
+ $tip.find('.content > *')[ $.type(content) == 'object' ? 'append' : 'html' ](content)
+
$tip[0].className = 'popover'
}
+ , hasContent: function () {
+ return this.getTitle() || this.getContent()
+ }
+
, getContent: function () {
var content
, $e = this.$element
, o = this.options
if (typeof this.options.content == 'string') {
- content = $e.attr(o.content)
+ content = $e.attr(this.options.content)
} else if (typeof this.options.content == 'function') {
content = this.options.content.call(this.$element[0])
}
+
return content
}
, tip: function() {
if (!this.$tip) {
this.$tip = $('<div class="popover" />')
- .html('<div class="arrow"></div><div class="inner"><h3 class="title"></h3><div class="content"><p></p></div></div>')
+ .html(this.options.template)
}
return this.$tip
}
})
+
/* POPOVER PLUGIN DEFINITION
* ======================= */
@@ -71,6 +83,12 @@
return this
}
- $.fn.popover.defaults = $.extend({} , $.fn.twipsy.defaults, { content: 'data-content', placement: 'right'})
+ $.fn.popover.defaults = $.extend({} , $.fn.twipsy.defaults, {
+ placement: 'right'
+ , content: 'data-content'
+ , template: '<div class="arrow"></div><div class="inner"><h3 class="title"></h3><div class="content"><p></p></div></div>'
+ })
+
+ $.fn.twipsy.rejectAttrOptions.push( 'content' )
-}( window.jQuery || window.ender ); \ No newline at end of file
+}( window.jQuery || window.ender ) \ No newline at end of file
diff --git a/js/bootstrap-scrollspy.js b/js/bootstrap-scrollspy.js
index 1269d91ec..fe34019ff 100644
--- a/js/bootstrap-scrollspy.js
+++ b/js/bootstrap-scrollspy.js
@@ -17,36 +17,43 @@
* limitations under the License.
* ============================================================== */
-
!function ( $ ) {
- var $window = $(window)
+ "use strict"
+
+ /* SCROLLSPY CLASS DEFINITION
+ * ========================== */
- function ScrollSpy() {
+ function ScrollSpy( element ) {
var process = $.proxy(this.process, this)
- this.$topbar = $('body')
- this.selector = '[data-scrollspy] li > a'
+
+ this.$scrollElement = $(element).bind('scroll.scroll.data-api', process)
+ this.selector = (this.$scrollElement.attr('data-target')
+ || this.$scrollElement.attr('href')
+ || '') + ' .nav li > a'
+ this.$body = $('body').delegate(this.selector, 'click.scroll.data-api', process)
+
this.refresh()
- this.$topbar.delegate(this.selector, 'click', process)
- $window.scroll(process)
this.process()
}
ScrollSpy.prototype = {
refresh: function () {
- this.targets = this.$topbar.find(this.selector).map(function () {
- var href = $(this).attr('href')
- return /^#\w/.test(href) && $(href).length ? href : null
- })
+ this.targets = this.$body
+ .find(this.selector)
+ .map(function () {
+ var href = $(this).attr('href')
+ return /^#\w/.test(href) && $(href).length ? href : null
+ })
this.offsets = $.map(this.targets, function (id) {
- return $(id).offset().top
+ return $(id).position().top
})
}
, process: function () {
- var scrollTop = $window.scrollTop() + 10
+ var scrollTop = this.$scrollElement.scrollTop() + 10
, offsets = this.offsets
, targets = this.targets
, activeTarget = this.activeTarget
@@ -65,11 +72,11 @@
this.activeTarget = target
- this.$topbar
+ this.$body
.find(this.selector).parent('.active')
.removeClass('active')
- active = this.$topbar
+ active = this.$body
.find(this.selector + '[href="' + target + '"]')
.parent('li')
.addClass('active')
@@ -77,13 +84,29 @@
if ( active.parent('.dropdown-menu') ) {
active.closest('li.dropdown').addClass('active')
}
-
}
}
- $(function () {
- new ScrollSpy()
- })
+
+ /* SCROLLSPY PLUGIN DEFINITION
+ * =========================== */
+
+ $.fn.scrollspy = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('scrollspy')
+ if (!data) $this.data('scrollspy', (data = new ScrollSpy(this)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.scrollspy.ScrollSpy = ScrollSpy
+
+
+ /* SCROLLSPY DATA-API
+ * ============== */
+
+ $(function () { $('[data-spy="scroll"]').scrollspy() })
}( window.jQuery || window.ender ) \ No newline at end of file
diff --git a/js/bootstrap-tab.js b/js/bootstrap-tab.js
new file mode 100644
index 000000000..ba956cbe8
--- /dev/null
+++ b/js/bootstrap-tab.js
@@ -0,0 +1,102 @@
+/* ========================================================
+ * bootstrap-tabs.js v2.0.0
+ * http://twitter.github.com/bootstrap/javascript.html#tabs
+ * ========================================================
+ * Copyright 2011 Twitter, Inc.
+ *
+ * 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( $ ){
+
+ "use strict"
+
+ /* TAB CLASS DEFINITION
+ * ==================== */
+
+ var Tab = function ( element ) {
+ this.element = $(element)
+ }
+
+ Tab.prototype = {
+
+ show: function () {
+ var $this = this.element
+ , $ul = $this.closest('ul:not(.dropdown-menu)')
+ , href = $this.attr('data-target') || $this.attr('href')
+ , previous
+ , $href
+
+ if ( $this.parent('li').hasClass('active') ) return
+
+ previous = $ul.find('.active a').last()[0]
+
+ $this.trigger({
+ type: 'show'
+ , relatedTarget: previous
+ })
+
+ $href = $(href)
+
+ this.activate($this.parent('li'), $ul)
+ this.activate($href, $href.parent())
+
+ $this.trigger({
+ type: 'shown'
+ , relatedTarget: previous
+ })
+ }
+
+ , activate: function ( element, container ) {
+ container
+ .find('> .active')
+ .removeClass('active')
+ .find('> .dropdown-menu > .active')
+ .removeClass('active')
+
+ element.addClass('active')
+
+ if ( element.parent('.dropdown-menu') ) {
+ element.closest('li.dropdown').addClass('active')
+ }
+ }
+ }
+
+
+ /* TAB PLUGIN DEFINITION
+ * ===================== */
+
+ $.fn.tab = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('tab')
+ if (!data) $this.data('tab', (data = new Tab(this)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.tab.Tab = Tab
+
+
+ /* TAB DATA-API
+ * ============ */
+
+ $(document).ready(function () {
+ $('body').delegate('[data-toggle="tab"], [data-toggle="pill"]', 'click.tab.data-api', function (e) {
+ e.preventDefault()
+ $(this).tab('show')
+ })
+ })
+
+}( window.jQuery || window.ender ) \ No newline at end of file
diff --git a/js/bootstrap-tabs.js b/js/bootstrap-tabs.js
deleted file mode 100644
index 86bd4784f..000000000
--- a/js/bootstrap-tabs.js
+++ /dev/null
@@ -1,71 +0,0 @@
-/* ========================================================
- * bootstrap-tabs.js v2.0.0
- * http://twitter.github.com/bootstrap/javascript.html#tabs
- * ========================================================
- * Copyright 2011 Twitter, Inc.
- *
- * 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( $ ){
-
- function activate ( element, container ) {
- container
- .find('> .active')
- .removeClass('active')
- .find('> .dropdown-menu > .active')
- .removeClass('active')
-
- element.addClass('active')
-
- if ( element.parent('.dropdown-menu') ) {
- element.closest('li.dropdown').addClass('active')
- }
- }
-
- function tab( e ) {
- var $this = $(this)
- , $ul = $this.closest('ul:not(.dropdown-menu)')
- , href = $this.attr('href')
- , previous
-
- if ( /^#\w+/.test(href) ) {
- e.preventDefault()
-
- if ( $this.parent('li').hasClass('active') ) {
- return
- }
-
- previous = $ul.find('.active a').last()[0]
- $href = $(href)
-
- activate($this.parent('li'), $ul)
- activate($href, $href.parent())
-
- $this.trigger({
- type: 'change'
- , relatedTarget: previous
- })
- }
- }
-
-
- /* TABS/PILLS PLUGIN DEFINITION
- * ============================ */
-
- $(function () {
- $('body').delegate('ul[data-tabs] > li > a, ul[data-pills] > li > a', 'click', tab)
- })
-
-}( window.jQuery || window.ender ); \ No newline at end of file
diff --git a/js/bootstrap-transitions.js b/js/bootstrap-transition.js
index 49b5338a8..25f8b111f 100644
--- a/js/bootstrap-transitions.js
+++ b/js/bootstrap-transition.js
@@ -38,7 +38,7 @@ $(function () {
transitionEnd = "oTransitionEnd"
}
return transitionEnd
- })()
+ }())
}
})()
diff --git a/js/bootstrap-twipsy.js b/js/bootstrap-twipsy.js
index 7c195fbc7..fe4469a23 100644
--- a/js/bootstrap-twipsy.js
+++ b/js/bootstrap-twipsy.js
@@ -18,9 +18,10 @@
* limitations under the License.
* ========================================================== */
-
!function( $ ) {
+ "use strict"
+
/* TWIPSY PUBLIC CLASS DEFINITION
* ============================== */
@@ -41,7 +42,7 @@
, $tip
, tp
- if (this.getTitle() && this.enabled) {
+ if (this.hasContent() && this.enabled) {
$tip = this.tip()
this.setContent()
@@ -61,7 +62,8 @@
actualWidth = $tip[0].offsetWidth
actualHeight = $tip[0].offsetHeight
- placement = _.maybeCall(this.options.placement, this.$element[0])
+
+ placement = maybeCall(this.options.placement, this, [ $tip[0], this.$element[0] ])
switch (placement) {
case 'below':
@@ -87,7 +89,7 @@
, setContent: function () {
var $tip = this.tip()
- $tip.find('.twipsy-inner')[this.options.html ? 'html' : 'text'](this.getTitle())
+ $tip.find('.twipsy-inner').html(this.getTitle())
$tip[0].className = 'twipsy'
}
@@ -102,7 +104,7 @@
}
$.support.transition && this.$tip.hasClass('fade') ?
- $tip.bind($.support.transition.end, removeElement) :
+ $tip.bind( $.support.transition.end, removeElement) :
removeElement()
}
@@ -113,6 +115,10 @@
}
}
+ , hasContent: function () {
+ return this.getTitle()
+ }
+
, getTitle: function() {
var title
, $e = this.$element
@@ -128,14 +134,11 @@
title = ('' + title).replace(/(^\s*|\s*$)/, "")
- return title || o.fallback
+ return title
}
, tip: function() {
- if (!this.$tip) {
- this.$tip = $('<div class="twipsy" />').html('<div class="twipsy-arrow"></div><div class="twipsy-inner"></div>')
- }
- return this.$tip
+ return this.$tip = this.$tip || $('<div class="twipsy" />').html(this.options.template)
}
, validate: function() {
@@ -158,21 +161,20 @@
this.enabled = !this.enabled
}
+ , toggle: function () {
+ this[this.tip().hasClass('in') ? 'hide' : 'show']()
+ }
+
}
/* TWIPSY PRIVATE METHODS
* ====================== */
- var _ = {
-
- maybeCall: function ( thing, ctx ) {
- return (typeof thing == 'function') ? (thing.call(ctx)) : thing
- }
-
+ function maybeCall ( thing, ctx, args ) {
+ return typeof thing == 'function' ? thing.apply(ctx, args) : thing
}
-
/* TWIPSY PLUGIN DEFINITION
* ======================== */
@@ -187,18 +189,22 @@
, eventIn
, eventOut
- if (options === true) {
- return this.data(name)
- } else if (typeof options == 'string') {
- twipsy = this.data(name)
- if (twipsy) {
- twipsy[options]()
- }
- return this
+ if (typeof options == 'string') {
+ return this.each(function (){
+ twipsy = $.data(this, name)
+ if (twipsy) twipsy[options]()
+ })
}
options = $.extend({}, $.fn[name].defaults, options)
+ if (options.delay && typeof options.delay == 'number') {
+ options.delay = {
+ show: options.delay
+ , hide: options.delay
+ }
+ }
+
function get(ele) {
var twipsy = $.data(ele, name)
@@ -214,7 +220,7 @@
var twipsy = get(this)
twipsy.hoverState = 'in'
- if (options.delayIn == 0) {
+ if (!options.delay || !options.delay.show) {
twipsy.show()
} else {
twipsy.fixTitle()
@@ -222,21 +228,21 @@
if (twipsy.hoverState == 'in') {
twipsy.show()
}
- }, options.delayIn)
+ }, options.delay.show)
}
}
function leave() {
var twipsy = get(this)
twipsy.hoverState = 'out'
- if (options.delayOut == 0) {
+ if (!options.delay || !options.delay.hide) {
twipsy.hide()
} else {
setTimeout(function() {
if (twipsy.hoverState == 'out') {
twipsy.hide()
}
- }, options.delayOut)
+ }, options.delay.hide)
}
}
@@ -260,19 +266,27 @@
$.fn.twipsy.defaults = {
animate: true
- , delayIn: 0
- , delayOut: 0
- , fallback: ''
+ , delay: 0
, placement: 'above'
- , html: false
, live: false
, offset: 0
- , title: 'title'
, trigger: 'hover'
+ , title: 'title'
+ , template: '<div class="twipsy-arrow"></div><div class="twipsy-inner"></div>'
}
+ $.fn.twipsy.rejectAttrOptions = [ 'title' ]
+
$.fn.twipsy.elementOptions = function(ele, options) {
- return $.metadata ? $.extend({}, options, $(ele).metadata()) : options
+ var data = $(ele).data()
+ , rejects = $.fn.twipsy.rejectAttrOptions
+ , i = rejects.length
+
+ while (i--) {
+ delete data[rejects[i]]
+ }
+
+ return $.extend({}, options, data)
}
-}( window.jQuery || window.ender ); \ No newline at end of file
+}( window.jQuery || window.ender ) \ No newline at end of file