191 changed files with 30115 additions and 25548 deletions
@ -1,5 +0,0 @@ |
|||
Bootstrap uses [GitHub's Releases feature](https://github.com/blog/1547-release-your-software) for its changelogs. |
|||
|
|||
See [the Releases section of our GitHub project](https://github.com/twbs/bootstrap/releases) for changelogs for each release version of Bootstrap. |
|||
|
|||
Release announcement posts on [the official Bootstrap blog](https://blog.getbootstrap.com) contain summaries of the most noteworthy changes made in each release. |
@ -1,355 +0,0 @@ |
|||
/*! |
|||
* Bootstrap's Gruntfile |
|||
* https://getbootstrap.com
|
|||
* Copyright 2013-2017 The Bootstrap Authors |
|||
* Copyright 2013-2017 Twitter, Inc. |
|||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
|||
*/ |
|||
|
|||
module.exports = function (grunt) { |
|||
'use strict' |
|||
|
|||
// Force use of Unix newlines
|
|||
grunt.util.linefeed = '\n' |
|||
|
|||
RegExp.quote = function (string) { |
|||
return string.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&') |
|||
} |
|||
|
|||
var path = require('path') |
|||
var isTravis = require('is-travis') |
|||
|
|||
var configBridge = grunt.file.readJSON('./grunt/configBridge.json', { encoding: 'utf8' }) |
|||
|
|||
Object.keys(configBridge.paths).forEach(function (key) { |
|||
configBridge.paths[key].forEach(function (val, i, arr) { |
|||
arr[i] = path.join('./docs', val) |
|||
}) |
|||
}) |
|||
|
|||
// Project configuration.
|
|||
grunt.initConfig({ |
|||
|
|||
// Metadata.
|
|||
pkg: grunt.file.readJSON('package.json'), |
|||
banner: '/*!\n' + |
|||
' * Bootstrap v<%= pkg.version %> (<%= pkg.homepage %>)\n' + |
|||
' * Copyright 2011-<%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' + |
|||
' * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n' + |
|||
' */\n', |
|||
jqueryCheck: 'if (typeof jQuery === \'undefined\') {\n' + |
|||
' throw new Error(\'Bootstrap\\\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\\\'s JavaScript.\')\n' + |
|||
'}\n', |
|||
jqueryVersionCheck: '+function ($) {\n' + |
|||
' var version = $.fn.jquery.split(\' \')[0].split(\'.\')\n' + |
|||
' if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] >= 4)) {\n' + |
|||
' throw new Error(\'Bootstrap\\\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0\')\n' + |
|||
' }\n' + |
|||
'}(jQuery);\n\n', |
|||
|
|||
// Task configuration.
|
|||
clean: { |
|||
dist: 'dist', |
|||
docs: 'docs/dist' |
|||
}, |
|||
|
|||
// JS build configuration
|
|||
babel: { |
|||
dev: { |
|||
options: { |
|||
sourceMap: true |
|||
}, |
|||
files: { |
|||
'js/dist/util.js' : 'js/src/util.js', |
|||
'js/dist/alert.js' : 'js/src/alert.js', |
|||
'js/dist/button.js' : 'js/src/button.js', |
|||
'js/dist/carousel.js' : 'js/src/carousel.js', |
|||
'js/dist/collapse.js' : 'js/src/collapse.js', |
|||
'js/dist/dropdown.js' : 'js/src/dropdown.js', |
|||
'js/dist/modal.js' : 'js/src/modal.js', |
|||
'js/dist/scrollspy.js' : 'js/src/scrollspy.js', |
|||
'js/dist/tab.js' : 'js/src/tab.js', |
|||
'js/dist/tooltip.js' : 'js/src/tooltip.js', |
|||
'js/dist/popover.js' : 'js/src/popover.js' |
|||
} |
|||
}, |
|||
dist: { |
|||
options: { |
|||
extends: '../../js/.babelrc' |
|||
}, |
|||
files: { |
|||
'<%= concat.bootstrap.dest %>' : '<%= concat.bootstrap.dest %>' |
|||
} |
|||
} |
|||
}, |
|||
|
|||
stamp: { |
|||
options: { |
|||
banner: '<%= banner %>\n<%= jqueryCheck %>\n<%= jqueryVersionCheck %>\n+function () {\n', |
|||
footer: '\n}();' |
|||
}, |
|||
bootstrap: { |
|||
files: { |
|||
src: '<%= concat.bootstrap.dest %>' |
|||
} |
|||
} |
|||
}, |
|||
|
|||
concat: { |
|||
options: { |
|||
// Custom function to remove all export and import statements
|
|||
process: function (src) { |
|||
return src.replace(/^(export|import).*/gm, '') |
|||
} |
|||
}, |
|||
bootstrap: { |
|||
src: [ |
|||
'js/src/util.js', |
|||
'js/src/alert.js', |
|||
'js/src/button.js', |
|||
'js/src/carousel.js', |
|||
'js/src/collapse.js', |
|||
'js/src/dropdown.js', |
|||
'js/src/modal.js', |
|||
'js/src/scrollspy.js', |
|||
'js/src/tab.js', |
|||
'js/src/tooltip.js', |
|||
'js/src/popover.js' |
|||
], |
|||
dest: 'dist/js/<%= pkg.name %>.js' |
|||
} |
|||
}, |
|||
|
|||
qunit: { |
|||
options: { |
|||
inject: 'js/tests/unit/phantom.js' |
|||
}, |
|||
files: 'js/tests/index.html' |
|||
}, |
|||
|
|||
// CSS build configuration
|
|||
copy: { |
|||
docs: { |
|||
expand: true, |
|||
cwd: 'dist/', |
|||
src: [ |
|||
'**/*' |
|||
], |
|||
dest: 'docs/dist/' |
|||
} |
|||
}, |
|||
|
|||
connect: { |
|||
server: { |
|||
options: { |
|||
port: 3000, |
|||
base: '.' |
|||
} |
|||
} |
|||
}, |
|||
|
|||
jekyll: { |
|||
options: { |
|||
bundleExec: true, |
|||
config: '_config.yml', |
|||
incremental: false |
|||
}, |
|||
docs: {}, |
|||
github: { |
|||
options: { |
|||
raw: 'github: true' |
|||
} |
|||
} |
|||
}, |
|||
|
|||
htmllint: { |
|||
options: { |
|||
ignore: [ |
|||
'Attribute “autocomplete” is only allowed when the input type is “color”, “date”, “datetime”, “datetime-local”, “email”, “hidden”, “month”, “number”, “password”, “range”, “search”, “tel”, “text”, “time”, “url”, or “week”.', |
|||
'Attribute “autocomplete” not allowed on element “button” at this point.', |
|||
'Consider using the “h1” element as a top-level heading only (all “h1” elements are treated as top-level headings by many screen readers and other tools).', |
|||
'Element “div” not allowed as child of element “progress” in this context. (Suppressing further errors from this subtree.)', |
|||
'Element “img” is missing required attribute “src”.', |
|||
'The “color” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.', |
|||
'The “date” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.', |
|||
'The “datetime” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.', |
|||
'The “datetime-local” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.', |
|||
'The “month” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.', |
|||
'The “time” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.', |
|||
'The “week” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.' |
|||
] |
|||
}, |
|||
src: ['_gh_pages/**/*.html', 'js/tests/visual/*.html'] |
|||
}, |
|||
|
|||
watch: { |
|||
src: { |
|||
files: '<%= concat.bootstrap.src %>', |
|||
tasks: ['babel:dev'] |
|||
}, |
|||
sass: { |
|||
files: 'scss/**/*.scss', |
|||
tasks: ['dist-css', 'docs'] |
|||
}, |
|||
docs: { |
|||
files: 'docs/assets/scss/**/*.scss', |
|||
tasks: ['dist-css', 'docs'] |
|||
} |
|||
}, |
|||
|
|||
'saucelabs-qunit': { |
|||
all: { |
|||
options: { |
|||
build: process.env.TRAVIS_JOB_ID, |
|||
concurrency: 10, |
|||
maxRetries: 3, |
|||
maxPollRetries: 4, |
|||
urls: ['http://127.0.0.1:3000/js/tests/index.html?hidepassed'], |
|||
browsers: grunt.file.readYAML('grunt/sauce_browsers.yml') |
|||
} |
|||
} |
|||
}, |
|||
|
|||
exec: { |
|||
'clean-css': { |
|||
command: 'npm run clean-css' |
|||
}, |
|||
'clean-css-docs': { |
|||
command: 'npm run clean-css-docs' |
|||
}, |
|||
postcss: { |
|||
command: 'npm run postcss' |
|||
}, |
|||
'postcss-docs': { |
|||
command: 'npm run postcss-docs' |
|||
}, |
|||
htmlhint: { |
|||
command: 'npm run htmlhint' |
|||
}, |
|||
sass: { |
|||
command: 'npm run sass' |
|||
}, |
|||
'sass-docs': { |
|||
command: 'npm run sass-docs' |
|||
}, |
|||
'scss-lint': { |
|||
command: 'npm run scss-lint' |
|||
}, |
|||
'scss-lint-docs': { |
|||
command: 'npm run scss-lint-docs' |
|||
}, |
|||
uglify: { |
|||
command: 'npm run uglify' |
|||
}, |
|||
'uglify-docs': { |
|||
command: 'npm run uglify-docs' |
|||
} |
|||
}, |
|||
|
|||
buildcontrol: { |
|||
options: { |
|||
dir: '_gh_pages', |
|||
commit: true, |
|||
push: true, |
|||
message: 'Built %sourceName% from commit %sourceCommit% on branch %sourceBranch%' |
|||
}, |
|||
pages: { |
|||
options: { |
|||
remote: 'git@github.com:twbs/derpstrap.git', |
|||
branch: 'gh-pages' |
|||
} |
|||
} |
|||
}, |
|||
|
|||
compress: { |
|||
main: { |
|||
options: { |
|||
archive: 'bootstrap-<%= pkg.version %>-dist.zip', |
|||
mode: 'zip', |
|||
level: 9, |
|||
pretty: true |
|||
}, |
|||
files: [ |
|||
{ |
|||
expand: true, |
|||
cwd: 'dist/', |
|||
src: ['**'], |
|||
dest: 'bootstrap-<%= pkg.version %>-dist' |
|||
} |
|||
] |
|||
} |
|||
} |
|||
|
|||
}) |
|||
|
|||
|
|||
// These plugins provide necessary tasks.
|
|||
require('load-grunt-tasks')(grunt) |
|||
require('time-grunt')(grunt) |
|||
|
|||
// Docs HTML validation task
|
|||
grunt.registerTask('validate-html', ['jekyll:docs', 'htmllint', 'exec:htmlhint']) |
|||
|
|||
var runSubset = function (subset) { |
|||
return !process.env.TWBS_TEST || process.env.TWBS_TEST === subset |
|||
} |
|||
var isUndefOrNonZero = function (val) { |
|||
return val === undefined || val !== '0' |
|||
} |
|||
|
|||
// Test task.
|
|||
var testSubtasks = [] |
|||
// Skip core tests if running a different subset of the test suite
|
|||
if (runSubset('core') && |
|||
// Skip core tests if this is a Savage build
|
|||
process.env.TRAVIS_REPO_SLUG !== 'twbs-savage/bootstrap') { |
|||
testSubtasks = testSubtasks.concat(['dist-css', 'dist-js', 'test-scss', 'qunit', 'docs']) |
|||
} |
|||
// Skip HTML validation if running a different subset of the test suite
|
|||
if (runSubset('validate-html') && |
|||
isTravis && |
|||
// Skip HTML5 validator when [skip validator] is in the commit message
|
|||
isUndefOrNonZero(process.env.TWBS_DO_VALIDATOR)) { |
|||
testSubtasks.push('validate-html') |
|||
} |
|||
// Only run Sauce Labs tests if there's a Sauce access key
|
|||
if (typeof process.env.SAUCE_ACCESS_KEY !== 'undefined' && |
|||
// Skip Sauce if running a different subset of the test suite
|
|||
runSubset('sauce-js-unit')) { |
|||
testSubtasks = testSubtasks.concat(['dist', 'docs-css', 'docs-js', 'clean:docs', 'copy:docs']) |
|||
// Skip Sauce on Travis when [skip sauce] is in the commit message
|
|||
if (isUndefOrNonZero(process.env.TWBS_DO_SAUCE)) { |
|||
testSubtasks.push('connect') |
|||
testSubtasks.push('saucelabs-qunit') |
|||
} |
|||
} |
|||
grunt.registerTask('test', testSubtasks) |
|||
|
|||
// JS distribution task.
|
|||
grunt.registerTask('dist-js', ['babel:dev', 'concat', 'babel:dist', 'stamp', 'exec:uglify']) |
|||
|
|||
grunt.registerTask('test-scss', ['exec:scss-lint']) |
|||
|
|||
// CSS distribution task.
|
|||
grunt.registerTask('sass-compile', ['exec:sass', 'exec:sass-docs']) |
|||
|
|||
grunt.registerTask('dist-css', ['sass-compile', 'exec:postcss', 'exec:clean-css', 'exec:clean-css-docs']) |
|||
|
|||
// Full distribution task.
|
|||
grunt.registerTask('dist', ['clean:dist', 'dist-css', 'dist-js']) |
|||
|
|||
// Default task.
|
|||
grunt.registerTask('default', ['clean:dist', 'test']) |
|||
|
|||
// Docs task.
|
|||
grunt.registerTask('docs-css', ['exec:clean-css-docs', 'exec:postcss-docs']) |
|||
grunt.registerTask('lint-docs-css', ['exec:scss-lint-docs']) |
|||
grunt.registerTask('docs-js', ['exec:uglify-docs']) |
|||
grunt.registerTask('docs', ['lint-docs-css', 'docs-css', 'docs-js', 'clean:docs', 'copy:docs']) |
|||
grunt.registerTask('docs-github', ['jekyll:github']) |
|||
|
|||
grunt.registerTask('prep-release', ['dist', 'docs', 'docs-github', 'compress']) |
|||
|
|||
// Publish to GitHub
|
|||
grunt.registerTask('publish', ['buildcontrol:pages']) |
|||
} |
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +1,8 @@ |
|||
/*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}template{display:none}[hidden]{display:none}html{-webkit-box-sizing:border-box;box-sizing:border-box}*,::after,::before{-webkit-box-sizing:inherit;box-sizing:inherit}@-ms-viewport{width:device-width}html{-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:1rem;font-weight:400;line-height:1.5;color:#292b2c;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{cursor:help}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}a{color:#0275d8;text-decoration:none}a:focus,a:hover{color:#014c8c;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle}[role=button]{cursor:pointer}[role=button],a,area,button,input,label,select,summary,textarea{-ms-touch-action:manipulation;touch-action:manipulation}table{border-collapse:collapse;background-color:transparent}caption{padding-top:.75rem;padding-bottom:.75rem;color:#636c72;text-align:left;caption-side:bottom}th{text-align:left}label{display:inline-block;margin-bottom:.5rem}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,select,textarea{line-height:inherit}input[type=checkbox]:disabled,input[type=radio]:disabled{cursor:not-allowed}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{-webkit-appearance:listbox}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit}input[type=search]{-webkit-appearance:none}output{display:inline-block}[hidden]{display:none!important}/*# sourceMappingURL=bootstrap-reboot.min.css.map */ |
|||
/*! |
|||
* Bootstrap Reboot v4.0.0 (https://getbootstrap.com) |
|||
* Copyright 2011-2018 The Bootstrap Authors |
|||
* Copyright 2011-2018 Twitter, Inc. |
|||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) |
|||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) |
|||
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}@-ms-viewport{width:device-width}article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg:not(:root){overflow:hidden}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important} |
|||
/*# sourceMappingURL=bootstrap-reboot.min.css.map */ |
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,110 +0,0 @@ |
|||
#!/usr/bin/env node
|
|||
|
|||
'use strict' |
|||
|
|||
/*! |
|||
* Script to update version number references in the project. |
|||
* Copyright 2017 The Bootstrap Authors |
|||
* Copyright 2017 Twitter, Inc. |
|||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
|||
*/ |
|||
|
|||
/* global Set */ |
|||
|
|||
var fs = require('fs') |
|||
var path = require('path') |
|||
var sh = require('shelljs') |
|||
sh.config.fatal = true |
|||
var sed = sh.sed |
|||
|
|||
// Blame TC39... https://github.com/benjamingr/RegExp.escape/issues/37
|
|||
RegExp.quote = function (string) { |
|||
return string.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&') |
|||
} |
|||
RegExp.quoteReplacement = function (string) { |
|||
return string.replace(/[$]/g, '$$') |
|||
} |
|||
|
|||
var DRY_RUN = false |
|||
|
|||
function walkAsync(directory, excludedDirectories, fileCallback, errback) { |
|||
if (excludedDirectories.has(path.parse(directory).base)) { |
|||
return |
|||
} |
|||
fs.readdir(directory, function (err, names) { |
|||
if (err) { |
|||
errback(err) |
|||
return |
|||
} |
|||
names.forEach(function (name) { |
|||
var filepath = path.join(directory, name) |
|||
fs.lstat(filepath, function (err, stats) { |
|||
if (err) { |
|||
process.nextTick(errback, err) |
|||
return |
|||
} |
|||
if (stats.isSymbolicLink()) { |
|||
return |
|||
} |
|||
else if (stats.isDirectory()) { |
|||
process.nextTick(walkAsync, filepath, excludedDirectories, fileCallback, errback) |
|||
} |
|||
else if (stats.isFile()) { |
|||
process.nextTick(fileCallback, filepath) |
|||
} |
|||
}) |
|||
}) |
|||
}) |
|||
} |
|||
|
|||
function replaceRecursively(directory, excludedDirectories, allowedExtensions, original, replacement) { |
|||
original = new RegExp(RegExp.quote(original), 'g') |
|||
replacement = RegExp.quoteReplacement(replacement) |
|||
var updateFile = !DRY_RUN ? function (filepath) { |
|||
if (allowedExtensions.has(path.parse(filepath).ext)) { |
|||
sed('-i', original, replacement, filepath) |
|||
} |
|||
} : function (filepath) { |
|||
if (allowedExtensions.has(path.parse(filepath).ext)) { |
|||
console.log('FILE: ' + filepath) |
|||
} |
|||
else { |
|||
console.log('EXCLUDED:' + filepath) |
|||
} |
|||
} |
|||
walkAsync(directory, excludedDirectories, updateFile, function (err) { |
|||
console.error('ERROR while traversing directory!:') |
|||
console.error(err) |
|||
process.exit(1) |
|||
}) |
|||
} |
|||
|
|||
function main(args) { |
|||
if (args.length !== 2) { |
|||
console.error('USAGE: change-version old_version new_version') |
|||
console.error('Got arguments:', args) |
|||
process.exit(1) |
|||
} |
|||
var oldVersion = args[0] |
|||
var newVersion = args[1] |
|||
var EXCLUDED_DIRS = new Set([ |
|||
'.git', |
|||
'node_modules', |
|||
'vendor' |
|||
]) |
|||
var INCLUDED_EXTENSIONS = new Set([ |
|||
// This extension whitelist is how we avoid modifying binary files
|
|||
'', |
|||
'.css', |
|||
'.html', |
|||
'.js', |
|||
'.json', |
|||
'.md', |
|||
'.scss', |
|||
'.txt', |
|||
'.yml' |
|||
]) |
|||
replaceRecursively('.', EXCLUDED_DIRS, INCLUDED_EXTENSIONS, oldVersion, newVersion) |
|||
} |
|||
|
|||
main(process.argv.slice(2)) |
@ -1,10 +0,0 @@ |
|||
{ |
|||
"paths": { |
|||
"docsJs": [ |
|||
"assets/js/vendor/anchor.min.js", |
|||
"assets/js/vendor/clipboard.min.js", |
|||
"assets/js/vendor/holder.min.js", |
|||
"assets/js/src/application.js" |
|||
] |
|||
} |
|||
} |
Binary file not shown.
File diff suppressed because it is too large
@ -1,42 +0,0 @@ |
|||
module.exports = { |
|||
use: [ |
|||
'postcss-flexbugs-fixes', |
|||
'autoprefixer' |
|||
], |
|||
map: { |
|||
inline: false, |
|||
annotation: true, |
|||
sourcesContent: true |
|||
}, |
|||
autoprefixer: { |
|||
browsers: [ |
|||
//
|
|||
// Official browser support policy:
|
|||
// https://v4-alpha.getbootstrap.com/getting-started/browsers-devices/#supported-browsers
|
|||
//
|
|||
'Chrome >= 35', // Exact version number here is kinda arbitrary
|
|||
// Rather than using Autoprefixer's native "Firefox ESR" version specifier string,
|
|||
// we deliberately hardcode the number. This is to avoid unwittingly severely breaking the previous ESR in the event that:
|
|||
// (a) we happen to ship a new Bootstrap release soon after the release of a new ESR,
|
|||
// such that folks haven't yet had a reasonable amount of time to upgrade; and
|
|||
// (b) the new ESR has unprefixed CSS properties/values whose absence would severely break webpages
|
|||
// (e.g. `box-sizing`, as opposed to `background: linear-gradient(...)`).
|
|||
// Since they've been unprefixed, Autoprefixer will stop prefixing them,
|
|||
// thus causing them to not work in the previous ESR (where the prefixes were required).
|
|||
'Firefox >= 38', // Current Firefox Extended Support Release (ESR); https://www.mozilla.org/en-US/firefox/organizations/faq/
|
|||
// Note: Edge versions in Autoprefixer & Can I Use refer to the EdgeHTML rendering engine version,
|
|||
// NOT the Edge app version shown in Edge's "About" screen.
|
|||
// For example, at the time of writing, Edge 20 on an up-to-date system uses EdgeHTML 12.
|
|||
// See also https://github.com/Fyrd/caniuse/issues/1928
|
|||
'Edge >= 12', |
|||
'Explorer >= 10', |
|||
// Out of leniency, we prefix these 1 version further back than the official policy.
|
|||
'iOS >= 8', |
|||
'Safari >= 8', |
|||
// The following remain NOT officially supported, but we're lenient and include their prefixes to avoid severely breaking in them.
|
|||
'Android 2.3', |
|||
'Android >= 4', |
|||
'Opera >= 12' |
|||
] |
|||
} |
|||
} |
@ -1,84 +0,0 @@ |
|||
[ |
|||
# Docs: https://wiki.saucelabs.com/display/DOCS/Platform+Configurator |
|||
|
|||
{ |
|||
browserName: "safari", |
|||
platform: "OS X 10.11" |
|||
}, |
|||
{ |
|||
browserName: "chrome", |
|||
platform: "OS X 10.11", |
|||
version: "latest" |
|||
}, |
|||
{ |
|||
browserName: "firefox", |
|||
platform: "OS X 10.11", |
|||
version: "latest" |
|||
}, |
|||
|
|||
# Mac Opera not currently supported by Sauce Labs |
|||
|
|||
{ |
|||
browserName: "MicrosoftEdge", |
|||
platform: "Windows 10", |
|||
version: "latest" |
|||
}, |
|||
{ |
|||
browserName: "internet explorer", |
|||
version: "11", |
|||
platform: "Windows 8.1" |
|||
}, |
|||
{ |
|||
browserName: "internet explorer", |
|||
version: "10", |
|||
platform: "Windows 8" |
|||
}, |
|||
{ |
|||
browserName: "internet explorer", |
|||
version: "9", |
|||
platform: "Windows 7" |
|||
}, |
|||
|
|||
{ |
|||
browserName: "chrome", |
|||
platform: "Windows 10", |
|||
version: "latest" |
|||
}, |
|||
{ |
|||
browserName: "firefox", |
|||
platform: "Windows 10", |
|||
version: "latest" |
|||
}, |
|||
|
|||
# Win Opera 15+ not currently supported by Sauce Labs |
|||
|
|||
{ |
|||
browserName: "Safari", |
|||
deviceName: "iPhone Simulator", |
|||
platformVersion: "9.3", |
|||
platformName: "iOS" |
|||
}, |
|||
|
|||
# iOS Chrome not currently supported by Sauce Labs |
|||
|
|||
# Linux (unofficial) |
|||
{ |
|||
browserName: "chrome", |
|||
platform: "Linux", |
|||
version: "latest" |
|||
}, |
|||
{ |
|||
browserName: "firefox", |
|||
platform: "Linux", |
|||
version: "latest" |
|||
}, |
|||
|
|||
# Android |
|||
{ |
|||
platform: "Linux", |
|||
browserName: "android", |
|||
deviceName: "Android Emulator", |
|||
version: "latest", |
|||
deviceType: "phone" |
|||
} |
|||
] |
@ -1,28 +0,0 @@ |
|||
#!/bin/bash |
|||
# Upload built docs to preview.twbsapps.com |
|||
|
|||
if [ "$TRAVIS_REPO_SLUG" != twbs-savage/bootstrap ]; then exit 0; fi |
|||
|
|||
# Add build metadata to version |
|||
sed -i "/^current_version:/ s/\$/+pr.${TRAVIS_COMMIT}/" _config.yml |
|||
# Fix URLs since the site's root is now a subdirectory |
|||
echo "baseurl: /c/${TRAVIS_COMMIT}" >> _config.yml |
|||
bundle exec jekyll build --destination "$TRAVIS_COMMIT" |
|||
|
|||
# Install gcloud & gsutil |
|||
GSUTIL_VERSION=$(gsutil version | cut -d ' ' -f 3) |
|||
if [ ! -d "${HOME}/google-cloud-sdk" ] || [ "${GSUTIL_VERSION}" != '4.19' ]; then |
|||
rm -rf "${HOME}/google-cloud-sdk" # Kill Travis' outdated non-updateable preinstalled version |
|||
echo 'Installing google-cloud-sdk...' |
|||
export CLOUDSDK_CORE_DISABLE_PROMPTS=1 |
|||
time (curl -S -s https://sdk.cloud.google.com | bash &>/dev/null) |
|||
echo 'Done.' |
|||
fi |
|||
source "${HOME}/google-cloud-sdk/path.bash.inc" |
|||
|
|||
openssl aes-256-cbc -K $encrypted_2b749c8e6327_key -iv $encrypted_2b749c8e6327_iv -in grunt/gcp-key.json.enc -out grunt/gcp-key.json -d |
|||
gcloud auth activate-service-account "$GCP_SERVICE_ACCOUNT" --key-file grunt/gcp-key.json &> /dev/null || (echo 'GCP login failed!'; exit 1) |
|||
|
|||
echo "Uploading to http://preview.twbsapps.com/c/${TRAVIS_COMMIT} ..." |
|||
time gsutil -q -m cp -z html,css,js,svg -r "./${TRAVIS_COMMIT}" gs://preview.twbsapps.com/c/ |
|||
echo 'Done.' |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,23 @@ |
|||
/** |
|||
* -------------------------------------------------------------------------- |
|||
* Bootstrap (v4.0.0-alpha.6): index.js |
|||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
|||
* -------------------------------------------------------------------------- |
|||
*/ |
|||
(function ($) { |
|||
if (typeof $ === 'undefined') { |
|||
throw new TypeError('Bootstrap\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\'s JavaScript.'); |
|||
} |
|||
|
|||
var version = $.fn.jquery.split(' ')[0].split('.'); |
|||
var minMajor = 1; |
|||
var ltMajor = 2; |
|||
var minMinor = 9; |
|||
var minPatch = 1; |
|||
var maxMajor = 4; |
|||
|
|||
if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) { |
|||
throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0'); |
|||
} |
|||
})($); |
|||
//# sourceMappingURL=index.js.map
|
@ -0,0 +1 @@ |
|||
{"version":3,"sources":["../src/index.js"],"names":["$","TypeError","version","fn","jquery","split","minMajor","ltMajor","minMinor","minPatch","maxMajor","Error"],"mappings":"AAaA;;;;;;AAOA,CAAC,UAACA,CAAD,EAAO;AACN,MAAI,OAAOA,CAAP,KAAa,WAAjB,EAA8B;AAC5B,UAAM,IAAIC,SAAJ,CAAc,kGAAd,CAAN;AACD;;AAED,MAAMC,UAAUF,EAAEG,EAAF,CAAKC,MAAL,CAAYC,KAAZ,CAAkB,GAAlB,EAAuB,CAAvB,EAA0BA,KAA1B,CAAgC,GAAhC,CAAhB;AACA,MAAMC,WAAW,CAAjB;AACA,MAAMC,UAAU,CAAhB;AACA,MAAMC,WAAW,CAAjB;AACA,MAAMC,WAAW,CAAjB;AACA,MAAMC,WAAW,CAAjB;;AAEA,MAAIR,QAAQ,CAAR,IAAaK,OAAb,IAAwBL,QAAQ,CAAR,IAAaM,QAArC,IAAiDN,QAAQ,CAAR,MAAeI,QAAf,IAA2BJ,QAAQ,CAAR,MAAeM,QAA1C,IAAsDN,QAAQ,CAAR,IAAaO,QAApH,IAAgIP,QAAQ,CAAR,KAAcQ,QAAlJ,EAA4J;AAC1J,UAAM,IAAIC,KAAJ,CAAU,8EAAV,CAAN;AACD;AACF,CAfD,EAeGX,CAfH","file":"index.js","sourcesContent":["import $ from 'jquery'\nimport Alert from './alert'\nimport Button from './button'\nimport Carousel from './carousel'\nimport Collapse from './collapse'\nimport Dropdown from './dropdown'\nimport Modal from './modal'\nimport Popover from './popover'\nimport Scrollspy from './scrollspy'\nimport Tab from './tab'\nimport Tooltip from './tooltip'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-alpha.6): index.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n(($) => {\n if (typeof $ === 'undefined') {\n throw new TypeError('Bootstrap\\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\\'s JavaScript.')\n }\n\n const version = $.fn.jquery.split(' ')[0].split('.')\n const minMajor = 1\n const ltMajor = 2\n const minMinor = 9\n const minPatch = 1\n const maxMajor = 4\n\n if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) {\n throw new Error('Bootstrap\\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0')\n }\n})($)\n\nexport {\n Util,\n Alert,\n Button,\n Carousel,\n Collapse,\n Dropdown,\n Modal,\n Popover,\n Scrollspy,\n Tab,\n Tooltip\n}\n"]} |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,50 @@ |
|||
import $ from 'jquery' |
|||
import Alert from './alert' |
|||
import Button from './button' |
|||
import Carousel from './carousel' |
|||
import Collapse from './collapse' |
|||
import Dropdown from './dropdown' |
|||
import Modal from './modal' |
|||
import Popover from './popover' |
|||
import Scrollspy from './scrollspy' |
|||
import Tab from './tab' |
|||
import Tooltip from './tooltip' |
|||
import Util from './util' |
|||
|
|||
/** |
|||
* -------------------------------------------------------------------------- |
|||
* Bootstrap (v4.0.0-alpha.6): index.js |
|||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
|||
* -------------------------------------------------------------------------- |
|||
*/ |
|||
|
|||
(($) => { |
|||
if (typeof $ === 'undefined') { |
|||
throw new TypeError('Bootstrap\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\'s JavaScript.') |
|||
} |
|||
|
|||
const version = $.fn.jquery.split(' ')[0].split('.') |
|||
const minMajor = 1 |
|||
const ltMajor = 2 |
|||
const minMinor = 9 |
|||
const minPatch = 1 |
|||
const maxMajor = 4 |
|||
|
|||
if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) { |
|||
throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0') |
|||
} |
|||
})($) |
|||
|
|||
export { |
|||
Util, |
|||
Alert, |
|||
Button, |
|||
Carousel, |
|||
Collapse, |
|||
Dropdown, |
|||
Modal, |
|||
Popover, |
|||
Scrollspy, |
|||
Tab, |
|||
Tooltip |
|||
} |
@ -1,61 +0,0 @@ |
|||
## How does Bootstrap's test suite work? |
|||
|
|||
Bootstrap uses [QUnit](https://qunitjs.com/), a powerful, easy-to-use JavaScript unit test framework. Each plugin has a file dedicated to its tests in `unit/<plugin-name>.js`. |
|||
|
|||
* `unit/` contains the unit test files for each Bootstrap plugin. |
|||
* `vendor/` contains third-party testing-related code (QUnit and jQuery). |
|||
* `visual/` contains "visual" tests which are run interactively in real browsers and require manual verification by humans. |
|||
|
|||
To run the unit test suite via [PhantomJS](http://phantomjs.org/), run `grunt test-js`. |
|||
|
|||
To run the unit test suite via a real web browser, open `index.html` in the browser. |
|||
|
|||
|
|||
## How do I add a new unit test? |
|||
|
|||
1. Locate and open the file dedicated to the plugin which you need to add tests to (`unit/<plugin-name>.js`). |
|||
2. Review the [QUnit API Documentation](https://api.qunitjs.com/) and use the existing tests as references for how to structure your new tests. |
|||
3. Write the necessary unit test(s) for the new or revised functionality. |
|||
4. Run `grunt test-js` to see the results of your newly-added test(s). |
|||
|
|||
**Note:** Your new unit tests should fail before your changes are applied to the plugin, and should pass after your changes are applied to the plugin. |
|||
|
|||
## What should a unit test look like? |
|||
|
|||
* Each test should have a unique name clearly stating what unit is being tested. |
|||
* Each test should test only one unit per test, although one test can include several assertions. Create multiple tests for multiple units of functionality. |
|||
* Each test should begin with [`assert.expect`](https://api.qunitjs.com/expect/) to ensure that the expected assertions are run. |
|||
* Each test should follow the project's [JavaScript Code Guidelines](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md#js) |
|||
|
|||
### Example tests |
|||
|
|||
```javascript |
|||
// Synchronous test |
|||
QUnit.test('should describe the unit being tested', function (assert) { |
|||
assert.expect(1) |
|||
var templateHTML = '<div class="alert alert-danger fade in">' |
|||
+ '<a class="close" href="#" data-dismiss="alert">×</a>' |
|||
+ '<p><strong>Template necessary for the test.</p>' |
|||
+ '</div>' |
|||
var $alert = $(templateHTML).appendTo('#qunit-fixture').bootstrapAlert() |
|||
|
|||
$alert.find('.close').click() |
|||
|
|||
// Make assertion |
|||
assert.strictEqual($alert.hasClass('in'), false, 'remove .in class on .close click') |
|||
}) |
|||
|
|||
// Asynchronous test |
|||
QUnit.test('should describe the unit being tested', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
$('<div title="tooltip title"></div>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('shown.bs.tooltip', function () { |
|||
assert.ok(true, '"shown" event was fired after calling "show"') |
|||
done() |
|||
}) |
|||
.bootstrapTooltip('show') |
|||
}) |
|||
``` |
@ -1,79 +0,0 @@ |
|||
$(function () { |
|||
'use strict' |
|||
|
|||
QUnit.module('alert plugin') |
|||
|
|||
QUnit.test('should be defined on jquery object', function (assert) { |
|||
assert.expect(1) |
|||
assert.ok($(document.body).alert, 'alert method is defined') |
|||
}) |
|||
|
|||
QUnit.module('alert', { |
|||
beforeEach: function () { |
|||
// Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
|
|||
$.fn.bootstrapAlert = $.fn.alert.noConflict() |
|||
}, |
|||
afterEach: function () { |
|||
$.fn.alert = $.fn.bootstrapAlert |
|||
delete $.fn.bootstrapAlert |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should provide no conflict', function (assert) { |
|||
assert.expect(1) |
|||
assert.strictEqual($.fn.alert, undefined, 'alert was set back to undefined (org value)') |
|||
}) |
|||
|
|||
QUnit.test('should return jquery collection containing the element', function (assert) { |
|||
assert.expect(2) |
|||
var $el = $('<div/>') |
|||
var $alert = $el.bootstrapAlert() |
|||
assert.ok($alert instanceof $, 'returns jquery collection') |
|||
assert.strictEqual($alert[0], $el[0], 'collection contains element') |
|||
}) |
|||
|
|||
QUnit.test('should fade element out on clicking .close', function (assert) { |
|||
assert.expect(1) |
|||
var alertHTML = '<div class="alert alert-danger fade show">' |
|||
+ '<a class="close" href="#" data-dismiss="alert">×</a>' |
|||
+ '<p><strong>Holy guacamole!</strong> Best check yo self, you\'re not looking too good.</p>' |
|||
+ '</div>' |
|||
|
|||
var $alert = $(alertHTML).bootstrapAlert().appendTo($('#qunit-fixture')) |
|||
|
|||
$alert.find('.close').trigger('click') |
|||
|
|||
assert.strictEqual($alert.hasClass('show'), false, 'remove .show class on .close click') |
|||
}) |
|||
|
|||
QUnit.test('should remove element when clicking .close', function (assert) { |
|||
assert.expect(2) |
|||
var alertHTML = '<div class="alert alert-danger fade show">' |
|||
+ '<a class="close" href="#" data-dismiss="alert">×</a>' |
|||
+ '<p><strong>Holy guacamole!</strong> Best check yo self, you\'re not looking too good.</p>' |
|||
+ '</div>' |
|||
var $alert = $(alertHTML).appendTo('#qunit-fixture').bootstrapAlert() |
|||
|
|||
assert.notEqual($('#qunit-fixture').find('.alert').length, 0, 'element added to dom') |
|||
|
|||
$alert.find('.close').trigger('click') |
|||
|
|||
assert.strictEqual($('#qunit-fixture').find('.alert').length, 0, 'element removed from dom') |
|||
}) |
|||
|
|||
QUnit.test('should not fire closed when close is prevented', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
$('<div class="alert"/>') |
|||
.on('close.bs.alert', function (e) { |
|||
e.preventDefault() |
|||
assert.ok(true, 'close event fired') |
|||
done() |
|||
}) |
|||
.on('closed.bs.alert', function () { |
|||
assert.ok(false, 'closed event fired') |
|||
}) |
|||
.bootstrapAlert('close') |
|||
}) |
|||
|
|||
}) |
@ -1,141 +0,0 @@ |
|||
$(function () { |
|||
'use strict' |
|||
|
|||
QUnit.module('button plugin') |
|||
|
|||
QUnit.test('should be defined on jquery object', function (assert) { |
|||
assert.expect(1) |
|||
assert.ok($(document.body).button, 'button method is defined') |
|||
}) |
|||
|
|||
QUnit.module('button', { |
|||
beforeEach: function () { |
|||
// Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
|
|||
$.fn.bootstrapButton = $.fn.button.noConflict() |
|||
}, |
|||
afterEach: function () { |
|||
$.fn.button = $.fn.bootstrapButton |
|||
delete $.fn.bootstrapButton |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should provide no conflict', function (assert) { |
|||
assert.expect(1) |
|||
assert.strictEqual($.fn.button, undefined, 'button was set back to undefined (org value)') |
|||
}) |
|||
|
|||
QUnit.test('should return jquery collection containing the element', function (assert) { |
|||
assert.expect(2) |
|||
var $el = $('<div/>') |
|||
var $button = $el.bootstrapButton() |
|||
assert.ok($button instanceof $, 'returns jquery collection') |
|||
assert.strictEqual($button[0], $el[0], 'collection contains element') |
|||
}) |
|||
|
|||
QUnit.test('should toggle active', function (assert) { |
|||
assert.expect(2) |
|||
var $btn = $('<button class="btn" data-toggle="button">mdo</button>') |
|||
assert.ok(!$btn.hasClass('active'), 'btn does not have active class') |
|||
$btn.bootstrapButton('toggle') |
|||
assert.ok($btn.hasClass('active'), 'btn has class active') |
|||
}) |
|||
|
|||
QUnit.test('should toggle active when btn children are clicked', function (assert) { |
|||
assert.expect(2) |
|||
var $btn = $('<button class="btn" data-toggle="button">mdo</button>') |
|||
var $inner = $('<i/>') |
|||
$btn |
|||
.append($inner) |
|||
.appendTo('#qunit-fixture') |
|||
assert.ok(!$btn.hasClass('active'), 'btn does not have active class') |
|||
$inner.trigger('click') |
|||
assert.ok($btn.hasClass('active'), 'btn has class active') |
|||
}) |
|||
|
|||
QUnit.test('should toggle aria-pressed', function (assert) { |
|||
assert.expect(2) |
|||
var $btn = $('<button class="btn" data-toggle="button" aria-pressed="false">redux</button>') |
|||
assert.strictEqual($btn.attr('aria-pressed'), 'false', 'btn aria-pressed state is false') |
|||
$btn.bootstrapButton('toggle') |
|||
assert.strictEqual($btn.attr('aria-pressed'), 'true', 'btn aria-pressed state is true') |
|||
}) |
|||
|
|||
QUnit.test('should toggle aria-pressed on buttons with container', function (assert) { |
|||
assert.expect(1) |
|||
var groupHTML = '<div class="btn-group" data-toggle="buttons">' + |
|||
'<button id="btn1" class="btn btn-secondary" type="button">One</button>' + |
|||
'<button class="btn btn-secondary" type="button">Two</button>' + |
|||
'</div>' |
|||
$('#qunit-fixture').append(groupHTML) |
|||
$('#btn1').bootstrapButton('toggle') |
|||
assert.strictEqual($('#btn1').attr('aria-pressed'), 'true') |
|||
}) |
|||
|
|||
QUnit.test('should toggle aria-pressed when btn children are clicked', function (assert) { |
|||
assert.expect(2) |
|||
var $btn = $('<button class="btn" data-toggle="button" aria-pressed="false">redux</button>') |
|||
var $inner = $('<i/>') |
|||
$btn |
|||
.append($inner) |
|||
.appendTo('#qunit-fixture') |
|||
assert.strictEqual($btn.attr('aria-pressed'), 'false', 'btn aria-pressed state is false') |
|||
$inner.trigger('click') |
|||
assert.strictEqual($btn.attr('aria-pressed'), 'true', 'btn aria-pressed state is true') |
|||
}) |
|||
|
|||
QUnit.test('should trigger input change event when toggled button has input field', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
var groupHTML = '<div class="btn-group" data-toggle="buttons">' |
|||
+ '<label class="btn btn-primary">' |
|||
+ '<input type="radio" id="radio" autocomplete="off">Radio' |
|||
+ '</label>' |
|||
+ '</div>' |
|||
var $group = $(groupHTML).appendTo('#qunit-fixture') |
|||
|
|||
$group.find('input').on('change', function (e) { |
|||
e.preventDefault() |
|||
assert.ok(true, 'change event fired') |
|||
done() |
|||
}) |
|||
|
|||
$group.find('label').trigger('click') |
|||
}) |
|||
|
|||
QUnit.test('should check for closest matching toggle', function (assert) { |
|||
assert.expect(12) |
|||
var groupHTML = '<div class="btn-group" data-toggle="buttons">' |
|||
+ '<label class="btn btn-primary active">' |
|||
+ '<input type="radio" name="options" id="option1" checked="true"> Option 1' |
|||
+ '</label>' |
|||
+ '<label class="btn btn-primary">' |
|||
+ '<input type="radio" name="options" id="option2"> Option 2' |
|||
+ '</label>' |
|||
+ '<label class="btn btn-primary">' |
|||
+ '<input type="radio" name="options" id="option3"> Option 3' |
|||
+ '</label>' |
|||
+ '</div>' |
|||
var $group = $(groupHTML).appendTo('#qunit-fixture') |
|||
|
|||
var $btn1 = $group.children().eq(0) |
|||
var $btn2 = $group.children().eq(1) |
|||
|
|||
assert.ok($btn1.hasClass('active'), 'btn1 has active class') |
|||
assert.ok($btn1.find('input').prop('checked'), 'btn1 is checked') |
|||
assert.ok(!$btn2.hasClass('active'), 'btn2 does not have active class') |
|||
assert.ok(!$btn2.find('input').prop('checked'), 'btn2 is not checked') |
|||
$btn2.find('input').trigger('click') |
|||
assert.ok(!$btn1.hasClass('active'), 'btn1 does not have active class') |
|||
assert.ok(!$btn1.find('input').prop('checked'), 'btn1 is not checked') |
|||
assert.ok($btn2.hasClass('active'), 'btn2 has active class') |
|||
assert.ok($btn2.find('input').prop('checked'), 'btn2 is checked') |
|||
|
|||
$btn2.find('input').trigger('click') // clicking an already checked radio should not un-check it
|
|||
assert.ok(!$btn1.hasClass('active'), 'btn1 does not have active class') |
|||
assert.ok(!$btn1.find('input').prop('checked'), 'btn1 is not checked') |
|||
assert.ok($btn2.hasClass('active'), 'btn2 has active class') |
|||
assert.ok($btn2.find('input').prop('checked'), 'btn2 is checked') |
|||
}) |
|||
|
|||
}) |
@ -1,825 +0,0 @@ |
|||
$(function () { |
|||
'use strict' |
|||
|
|||
QUnit.module('carousel plugin') |
|||
|
|||
QUnit.test('should be defined on jQuery object', function (assert) { |
|||
assert.expect(1) |
|||
assert.ok($(document.body).carousel, 'carousel method is defined') |
|||
}) |
|||
|
|||
QUnit.module('carousel', { |
|||
beforeEach: function () { |
|||
// Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
|
|||
$.fn.bootstrapCarousel = $.fn.carousel.noConflict() |
|||
}, |
|||
afterEach: function () { |
|||
$.fn.carousel = $.fn.bootstrapCarousel |
|||
delete $.fn.bootstrapCarousel |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should provide no conflict', function (assert) { |
|||
assert.expect(1) |
|||
assert.strictEqual($.fn.carousel, undefined, 'carousel was set back to undefined (orig value)') |
|||
}) |
|||
|
|||
QUnit.test('should throw explicit error on undefined method', function (assert) { |
|||
assert.expect(1) |
|||
var $el = $('<div/>') |
|||
$el.bootstrapCarousel() |
|||
try { |
|||
$el.bootstrapCarousel('noMethod') |
|||
} |
|||
catch (err) { |
|||
assert.strictEqual(err.message, 'No method named "noMethod"') |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should return jquery collection containing the element', function (assert) { |
|||
assert.expect(2) |
|||
var $el = $('<div/>') |
|||
var $carousel = $el.bootstrapCarousel() |
|||
assert.ok($carousel instanceof $, 'returns jquery collection') |
|||
assert.strictEqual($carousel[0], $el[0], 'collection contains element') |
|||
}) |
|||
|
|||
QUnit.test('should type check config options', function (assert) { |
|||
assert.expect(2) |
|||
|
|||
var message |
|||
var expectedMessage = 'CAROUSEL: Option "interval" provided type "string" but expected type "(number|boolean)".' |
|||
var config = { |
|||
interval: 'fat sux' |
|||
} |
|||
|
|||
try { |
|||
$('<div/>').bootstrapCarousel(config) |
|||
} catch (e) { |
|||
message = e.message |
|||
} |
|||
|
|||
assert.ok(message === expectedMessage, 'correct error message') |
|||
|
|||
config = { |
|||
keyboard: document.createElement('div') |
|||
} |
|||
expectedMessage = 'CAROUSEL: Option "keyboard" provided type "element" but expected type "boolean".' |
|||
|
|||
try { |
|||
$('<div/>').bootstrapCarousel(config) |
|||
} catch (e) { |
|||
message = e.message |
|||
} |
|||
|
|||
assert.ok(message === expectedMessage, 'correct error message') |
|||
}) |
|||
|
|||
|
|||
QUnit.test('should not fire slid when slide is prevented', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
$('<div class="carousel"/>') |
|||
.on('slide.bs.carousel', function (e) { |
|||
e.preventDefault() |
|||
assert.ok(true, 'slide event fired') |
|||
done() |
|||
}) |
|||
.on('slid.bs.carousel', function () { |
|||
assert.ok(false, 'slid event fired') |
|||
}) |
|||
.bootstrapCarousel('next') |
|||
}) |
|||
|
|||
QUnit.test('should reset when slide is prevented', function (assert) { |
|||
assert.expect(6) |
|||
var carouselHTML = '<div id="carousel-example-generic" class="carousel slide">' |
|||
+ '<ol class="carousel-indicators">' |
|||
+ '<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' |
|||
+ '<li data-target="#carousel-example-generic" data-slide-to="1"/>' |
|||
+ '<li data-target="#carousel-example-generic" data-slide-to="2"/>' |
|||
+ '</ol>' |
|||
+ '<div class="carousel-inner">' |
|||
+ '<div class="carousel-item active">' |
|||
+ '<div class="carousel-caption"/>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item">' |
|||
+ '<div class="carousel-caption"/>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item">' |
|||
+ '<div class="carousel-caption"/>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<a class="left carousel-control" href="#carousel-example-generic" data-slide="prev"/>' |
|||
+ '<a class="right carousel-control" href="#carousel-example-generic" data-slide="next"/>' |
|||
+ '</div>' |
|||
var $carousel = $(carouselHTML) |
|||
|
|||
var done = assert.async() |
|||
$carousel |
|||
.one('slide.bs.carousel', function (e) { |
|||
e.preventDefault() |
|||
setTimeout(function () { |
|||
assert.ok($carousel.find('.carousel-item:eq(0)').is('.active'), 'first item still active') |
|||
assert.ok($carousel.find('.carousel-indicators li:eq(0)').is('.active'), 'first indicator still active') |
|||
$carousel.bootstrapCarousel('next') |
|||
}, 0) |
|||
}) |
|||
.one('slid.bs.carousel', function () { |
|||
setTimeout(function () { |
|||
assert.ok(!$carousel.find('.carousel-item:eq(0)').is('.active'), 'first item still active') |
|||
assert.ok(!$carousel.find('.carousel-indicators li:eq(0)').is('.active'), 'first indicator still active') |
|||
assert.ok($carousel.find('.carousel-item:eq(1)').is('.active'), 'second item active') |
|||
assert.ok($carousel.find('.carousel-indicators li:eq(1)').is('.active'), 'second indicator active') |
|||
done() |
|||
}, 0) |
|||
}) |
|||
.bootstrapCarousel('next') |
|||
}) |
|||
|
|||
QUnit.test('should fire slide event with direction', function (assert) { |
|||
assert.expect(4) |
|||
var carouselHTML = '<div id="myCarousel" class="carousel slide">' |
|||
+ '<div class="carousel-inner">' |
|||
+ '<div class="carousel-item active">' |
|||
+ '<img alt="">' |
|||
+ '<div class="carousel-caption">' |
|||
+ '<h4>First Thumbnail label</h4>' |
|||
+ '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' |
|||
+ 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' |
|||
+ 'ultricies vehicula ut id elit.</p>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '<div class="carousel-caption">' |
|||
+ '<h4>Second Thumbnail label</h4>' |
|||
+ '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' |
|||
+ 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' |
|||
+ 'ultricies vehicula ut id elit.</p>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '<div class="carousel-caption">' |
|||
+ '<h4>Third Thumbnail label</h4>' |
|||
+ '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' |
|||
+ 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' |
|||
+ 'ultricies vehicula ut id elit.</p>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<a class="left carousel-control" href="#myCarousel" data-slide="prev">‹</a>' |
|||
+ '<a class="right carousel-control" href="#myCarousel" data-slide="next">›</a>' |
|||
+ '</div>' |
|||
var $carousel = $(carouselHTML) |
|||
|
|||
var done = assert.async() |
|||
|
|||
$carousel |
|||
.one('slide.bs.carousel', function (e) { |
|||
assert.ok(e.direction, 'direction present on next') |
|||
assert.strictEqual(e.direction, 'left', 'direction is left on next') |
|||
|
|||
$carousel |
|||
.one('slide.bs.carousel', function (e) { |
|||
assert.ok(e.direction, 'direction present on prev') |
|||
assert.strictEqual(e.direction, 'right', 'direction is right on prev') |
|||
done() |
|||
}) |
|||
.bootstrapCarousel('prev') |
|||
}) |
|||
.bootstrapCarousel('next') |
|||
}) |
|||
|
|||
QUnit.test('should fire slid event with direction', function (assert) { |
|||
assert.expect(4) |
|||
var carouselHTML = '<div id="myCarousel" class="carousel slide">' |
|||
+ '<div class="carousel-inner">' |
|||
+ '<div class="carousel-item active">' |
|||
+ '<img alt="">' |
|||
+ '<div class="carousel-caption">' |
|||
+ '<h4>First Thumbnail label</h4>' |
|||
+ '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' |
|||
+ 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' |
|||
+ 'ultricies vehicula ut id elit.</p>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '<div class="carousel-caption">' |
|||
+ '<h4>Second Thumbnail label</h4>' |
|||
+ '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' |
|||
+ 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' |
|||
+ 'ultricies vehicula ut id elit.</p>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '<div class="carousel-caption">' |
|||
+ '<h4>Third Thumbnail label</h4>' |
|||
+ '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' |
|||
+ 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' |
|||
+ 'ultricies vehicula ut id elit.</p>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<a class="left carousel-control" href="#myCarousel" data-slide="prev">‹</a>' |
|||
+ '<a class="right carousel-control" href="#myCarousel" data-slide="next">›</a>' |
|||
+ '</div>' |
|||
var $carousel = $(carouselHTML) |
|||
|
|||
var done = assert.async() |
|||
|
|||
$carousel |
|||
.one('slid.bs.carousel', function (e) { |
|||
assert.ok(e.direction, 'direction present on next') |
|||
assert.strictEqual(e.direction, 'left', 'direction is left on next') |
|||
|
|||
$carousel |
|||
.one('slid.bs.carousel', function (e) { |
|||
assert.ok(e.direction, 'direction present on prev') |
|||
assert.strictEqual(e.direction, 'right', 'direction is right on prev') |
|||
done() |
|||
}) |
|||
.bootstrapCarousel('prev') |
|||
}) |
|||
.bootstrapCarousel('next') |
|||
}) |
|||
|
|||
QUnit.test('should fire slide event with relatedTarget', function (assert) { |
|||
assert.expect(2) |
|||
var template = '<div id="myCarousel" class="carousel slide">' |
|||
+ '<div class="carousel-inner">' |
|||
+ '<div class="carousel-item active">' |
|||
+ '<img alt="">' |
|||
+ '<div class="carousel-caption">' |
|||
+ '<h4>First Thumbnail label</h4>' |
|||
+ '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' |
|||
+ 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' |
|||
+ 'ultricies vehicula ut id elit.</p>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '<div class="carousel-caption">' |
|||
+ '<h4>Second Thumbnail label</h4>' |
|||
+ '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' |
|||
+ 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' |
|||
+ 'ultricies vehicula ut id elit.</p>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '<div class="carousel-caption">' |
|||
+ '<h4>Third Thumbnail label</h4>' |
|||
+ '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' |
|||
+ 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' |
|||
+ 'ultricies vehicula ut id elit.</p>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<a class="left carousel-control" href="#myCarousel" data-slide="prev">‹</a>' |
|||
+ '<a class="right carousel-control" href="#myCarousel" data-slide="next">›</a>' |
|||
+ '</div>' |
|||
|
|||
var done = assert.async() |
|||
|
|||
$(template) |
|||
.on('slide.bs.carousel', function (e) { |
|||
assert.ok(e.relatedTarget, 'relatedTarget present') |
|||
assert.ok($(e.relatedTarget).hasClass('carousel-item'), 'relatedTarget has class "item"') |
|||
done() |
|||
}) |
|||
.bootstrapCarousel('next') |
|||
}) |
|||
|
|||
QUnit.test('should fire slid event with relatedTarget', function (assert) { |
|||
assert.expect(2) |
|||
var template = '<div id="myCarousel" class="carousel slide">' |
|||
+ '<div class="carousel-inner">' |
|||
+ '<div class="carousel-item active">' |
|||
+ '<img alt="">' |
|||
+ '<div class="carousel-caption">' |
|||
+ '<h4>First Thumbnail label</h4>' |
|||
+ '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' |
|||
+ 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' |
|||
+ 'ultricies vehicula ut id elit.</p>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '<div class="carousel-caption">' |
|||
+ '<h4>Second Thumbnail label</h4>' |
|||
+ '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' |
|||
+ 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' |
|||
+ 'ultricies vehicula ut id elit.</p>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '<div class="carousel-caption">' |
|||
+ '<h4>Third Thumbnail label</h4>' |
|||
+ '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' |
|||
+ 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' |
|||
+ 'ultricies vehicula ut id elit.</p>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<a class="left carousel-control" href="#myCarousel" data-slide="prev">‹</a>' |
|||
+ '<a class="right carousel-control" href="#myCarousel" data-slide="next">›</a>' |
|||
+ '</div>' |
|||
|
|||
var done = assert.async() |
|||
|
|||
$(template) |
|||
.on('slid.bs.carousel', function (e) { |
|||
assert.ok(e.relatedTarget, 'relatedTarget present') |
|||
assert.ok($(e.relatedTarget).hasClass('carousel-item'), 'relatedTarget has class "item"') |
|||
done() |
|||
}) |
|||
.bootstrapCarousel('next') |
|||
}) |
|||
|
|||
QUnit.test('should set interval from data attribute', function (assert) { |
|||
assert.expect(4) |
|||
var templateHTML = '<div id="myCarousel" class="carousel slide">' |
|||
+ '<div class="carousel-inner">' |
|||
+ '<div class="carousel-item active">' |
|||
+ '<img alt="">' |
|||
+ '<div class="carousel-caption">' |
|||
+ '<h4>First Thumbnail label</h4>' |
|||
+ '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' |
|||
+ 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' |
|||
+ 'ultricies vehicula ut id elit.</p>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '<div class="carousel-caption">' |
|||
+ '<h4>Second Thumbnail label</h4>' |
|||
+ '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' |
|||
+ 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' |
|||
+ 'ultricies vehicula ut id elit.</p>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '<div class="carousel-caption">' |
|||
+ '<h4>Third Thumbnail label</h4>' |
|||
+ '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' |
|||
+ 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' |
|||
+ 'ultricies vehicula ut id elit.</p>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<a class="left carousel-control" href="#myCarousel" data-slide="prev">‹</a>' |
|||
+ '<a class="right carousel-control" href="#myCarousel" data-slide="next">›</a>' |
|||
+ '</div>' |
|||
var $carousel = $(templateHTML) |
|||
$carousel.attr('data-interval', 1814) |
|||
|
|||
$carousel.appendTo('body') |
|||
$('[data-slide]').first().trigger('click') |
|||
assert.strictEqual($carousel.data('bs.carousel')._config.interval, 1814) |
|||
$carousel.remove() |
|||
|
|||
$carousel.appendTo('body').attr('data-modal', 'foobar') |
|||
$('[data-slide]').first().trigger('click') |
|||
assert.strictEqual($carousel.data('bs.carousel')._config.interval, 1814, 'even if there is an data-modal attribute set') |
|||
$carousel.remove() |
|||
|
|||
$carousel.appendTo('body') |
|||
$('[data-slide]').first().trigger('click') |
|||
$carousel.attr('data-interval', 1860) |
|||
$('[data-slide]').first().trigger('click') |
|||
assert.strictEqual($carousel.data('bs.carousel')._config.interval, 1814, 'attributes should be read only on initialization') |
|||
$carousel.remove() |
|||
|
|||
$carousel.attr('data-interval', false) |
|||
$carousel.appendTo('body') |
|||
$carousel.bootstrapCarousel(1) |
|||
assert.strictEqual($carousel.data('bs.carousel')._config.interval, false, 'data attribute has higher priority than default options') |
|||
$carousel.remove() |
|||
}) |
|||
|
|||
QUnit.test('should skip over non-items when using item indices', function (assert) { |
|||
assert.expect(2) |
|||
var templateHTML = '<div id="myCarousel" class="carousel" data-interval="1814">' |
|||
+ '<div class="carousel-inner">' |
|||
+ '<div class="carousel-item active">' |
|||
+ '<img alt="">' |
|||
+ '</div>' |
|||
+ '<script type="text/x-metamorph" id="thingy"/>' |
|||
+ '<div class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item">' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
var $template = $(templateHTML) |
|||
|
|||
$template.bootstrapCarousel() |
|||
|
|||
assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item active') |
|||
|
|||
$template.bootstrapCarousel(1) |
|||
|
|||
assert.strictEqual($template.find('.carousel-item')[1], $template.find('.active')[0], 'second item active') |
|||
}) |
|||
|
|||
QUnit.test('should skip over non-items when using next/prev methods', function (assert) { |
|||
assert.expect(2) |
|||
var templateHTML = '<div id="myCarousel" class="carousel" data-interval="1814">' |
|||
+ '<div class="carousel-inner">' |
|||
+ '<div class="carousel-item active">' |
|||
+ '<img alt="">' |
|||
+ '</div>' |
|||
+ '<script type="text/x-metamorph" id="thingy"/>' |
|||
+ '<div class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item">' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
var $template = $(templateHTML) |
|||
|
|||
$template.bootstrapCarousel() |
|||
|
|||
assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item active') |
|||
|
|||
$template.bootstrapCarousel('next') |
|||
|
|||
assert.strictEqual($template.find('.carousel-item')[1], $template.find('.active')[0], 'second item active') |
|||
}) |
|||
|
|||
QUnit.test('should go to previous item if left arrow key is pressed', function (assert) { |
|||
assert.expect(2) |
|||
var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false">' |
|||
+ '<div class="carousel-inner">' |
|||
+ '<div id="first" class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '</div>' |
|||
+ '<div id="second" class="carousel-item active">' |
|||
+ '<img alt="">' |
|||
+ '</div>' |
|||
+ '<div id="third" class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
var $template = $(templateHTML) |
|||
|
|||
$template.bootstrapCarousel() |
|||
|
|||
assert.strictEqual($template.find('.carousel-item')[1], $template.find('.active')[0], 'second item active') |
|||
|
|||
$template.trigger($.Event('keydown', { which: 37 })) |
|||
|
|||
assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item active') |
|||
}) |
|||
|
|||
QUnit.test('should go to next item if right arrow key is pressed', function (assert) { |
|||
assert.expect(2) |
|||
var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false">' |
|||
+ '<div class="carousel-inner">' |
|||
+ '<div id="first" class="carousel-item active">' |
|||
+ '<img alt="">' |
|||
+ '</div>' |
|||
+ '<div id="second" class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '</div>' |
|||
+ '<div id="third" class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
var $template = $(templateHTML) |
|||
|
|||
$template.bootstrapCarousel() |
|||
|
|||
assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item active') |
|||
|
|||
$template.trigger($.Event('keydown', { which: 39 })) |
|||
|
|||
assert.strictEqual($template.find('.carousel-item')[1], $template.find('.active')[0], 'second item active') |
|||
}) |
|||
|
|||
QUnit.test('should not prevent keydown if key is not ARROW_LEFT or ARROW_RIGHT', function (assert) { |
|||
assert.expect(2) |
|||
var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false">' |
|||
+ '<div class="carousel-inner">' |
|||
+ '<div id="first" class="carousel-item active">' |
|||
+ '<img alt="">' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
var $template = $(templateHTML) |
|||
|
|||
$template.bootstrapCarousel() |
|||
var done = assert.async() |
|||
|
|||
var eventArrowDown = $.Event('keydown', { which: 40 }) |
|||
var eventArrowUp = $.Event('keydown', { which: 38 }) |
|||
|
|||
$template.one('keydown', function (event) { |
|||
assert.strictEqual(event.isDefaultPrevented(), false) |
|||
}) |
|||
|
|||
$template.trigger(eventArrowDown) |
|||
|
|||
$template.one('keydown', function (event) { |
|||
assert.strictEqual(event.isDefaultPrevented(), false) |
|||
done() |
|||
}) |
|||
|
|||
$template.trigger(eventArrowUp) |
|||
}) |
|||
|
|||
QUnit.test('should support disabling the keyboard navigation', function (assert) { |
|||
assert.expect(3) |
|||
var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false" data-keyboard="false">' |
|||
+ '<div class="carousel-inner">' |
|||
+ '<div id="first" class="carousel-item active">' |
|||
+ '<img alt="">' |
|||
+ '</div>' |
|||
+ '<div id="second" class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '</div>' |
|||
+ '<div id="third" class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
var $template = $(templateHTML) |
|||
|
|||
$template.bootstrapCarousel() |
|||
|
|||
assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item active') |
|||
|
|||
$template.trigger($.Event('keydown', { which: 39 })) |
|||
|
|||
assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item still active after right arrow press') |
|||
|
|||
$template.trigger($.Event('keydown', { which: 37 })) |
|||
|
|||
assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item still active after left arrow press') |
|||
}) |
|||
|
|||
QUnit.test('should ignore keyboard events within <input>s and <textarea>s', function (assert) { |
|||
assert.expect(7) |
|||
var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false">' |
|||
+ '<div class="carousel-inner">' |
|||
+ '<div id="first" class="carousel-item active">' |
|||
+ '<img alt="">' |
|||
+ '<input type="text" id="in-put">' |
|||
+ '<textarea id="text-area"></textarea>' |
|||
+ '</div>' |
|||
+ '<div id="second" class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '</div>' |
|||
+ '<div id="third" class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
var $template = $(templateHTML) |
|||
var $input = $template.find('#in-put') |
|||
var $textarea = $template.find('#text-area') |
|||
|
|||
assert.strictEqual($input.length, 1, 'found <input>') |
|||
assert.strictEqual($textarea.length, 1, 'found <textarea>') |
|||
|
|||
$template.bootstrapCarousel() |
|||
|
|||
assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item active') |
|||
|
|||
|
|||
$input.trigger($.Event('keydown', { which: 39 })) |
|||
assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item still active after right arrow press in <input>') |
|||
|
|||
$input.trigger($.Event('keydown', { which: 37 })) |
|||
assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item still active after left arrow press in <input>') |
|||
|
|||
|
|||
$textarea.trigger($.Event('keydown', { which: 39 })) |
|||
assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item still active after right arrow press in <textarea>') |
|||
|
|||
$textarea.trigger($.Event('keydown', { which: 37 })) |
|||
assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item still active after left arrow press in <textarea>') |
|||
}) |
|||
|
|||
QUnit.test('should only add mouseenter and mouseleave listeners when not on mobile', function (assert) { |
|||
assert.expect(2) |
|||
var isMobile = 'ontouchstart' in document.documentElement |
|||
var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false" data-pause="hover">' |
|||
+ '<div class="carousel-inner">' |
|||
+ '<div id="first" class="carousel-item active">' |
|||
+ '<img alt="">' |
|||
+ '</div>' |
|||
+ '<div id="second" class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '</div>' |
|||
+ '<div id="third" class="carousel-item">' |
|||
+ '<img alt="">' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
var $template = $(templateHTML).bootstrapCarousel() |
|||
|
|||
$.each(['mouseover', 'mouseout'], function (i, type) { |
|||
assert.strictEqual(type in $._data($template[0], 'events'), !isMobile, 'does' + (isMobile ? ' not' : '') + ' listen for ' + type + ' events') |
|||
}) |
|||
}) |
|||
|
|||
QUnit.test('should wrap around from end to start when wrap option is true', function (assert) { |
|||
assert.expect(3) |
|||
var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="true">' |
|||
+ '<ol class="carousel-indicators">' |
|||
+ '<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' |
|||
+ '<li data-target="#carousel-example-generic" data-slide-to="1"/>' |
|||
+ '<li data-target="#carousel-example-generic" data-slide-to="2"/>' |
|||
+ '</ol>' |
|||
+ '<div class="carousel-inner">' |
|||
+ '<div class="carousel-item active" id="one">' |
|||
+ '<div class="carousel-caption"/>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item" id="two">' |
|||
+ '<div class="carousel-caption"/>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item" id="three">' |
|||
+ '<div class="carousel-caption"/>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<a class="left carousel-control" href="#carousel-example-generic" data-slide="prev"/>' |
|||
+ '<a class="right carousel-control" href="#carousel-example-generic" data-slide="next"/>' |
|||
+ '</div>' |
|||
var $carousel = $(carouselHTML) |
|||
var getActiveId = function () { return $carousel.find('.carousel-item.active').attr('id') } |
|||
|
|||
var done = assert.async() |
|||
|
|||
$carousel |
|||
.one('slid.bs.carousel', function () { |
|||
assert.strictEqual(getActiveId(), 'two', 'carousel slid from 1st to 2nd slide') |
|||
$carousel |
|||
.one('slid.bs.carousel', function () { |
|||
assert.strictEqual(getActiveId(), 'three', 'carousel slid from 2nd to 3rd slide') |
|||
$carousel |
|||
.one('slid.bs.carousel', function () { |
|||
assert.strictEqual(getActiveId(), 'one', 'carousel wrapped around and slid from 3rd to 1st slide') |
|||
done() |
|||
}) |
|||
.bootstrapCarousel('next') |
|||
}) |
|||
.bootstrapCarousel('next') |
|||
}) |
|||
.bootstrapCarousel('next') |
|||
}) |
|||
|
|||
QUnit.test('should wrap around from start to end when wrap option is true', function (assert) { |
|||
assert.expect(1) |
|||
var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="true">' |
|||
+ '<ol class="carousel-indicators">' |
|||
+ '<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' |
|||
+ '<li data-target="#carousel-example-generic" data-slide-to="1"/>' |
|||
+ '<li data-target="#carousel-example-generic" data-slide-to="2"/>' |
|||
+ '</ol>' |
|||
+ '<div class="carousel-inner">' |
|||
+ '<div class="carousel-item active" id="one">' |
|||
+ '<div class="carousel-caption"/>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item" id="two">' |
|||
+ '<div class="carousel-caption"/>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item" id="three">' |
|||
+ '<div class="carousel-caption"/>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<a class="left carousel-control" href="#carousel-example-generic" data-slide="prev"/>' |
|||
+ '<a class="right carousel-control" href="#carousel-example-generic" data-slide="next"/>' |
|||
+ '</div>' |
|||
var $carousel = $(carouselHTML) |
|||
|
|||
var done = assert.async() |
|||
|
|||
$carousel |
|||
.on('slid.bs.carousel', function () { |
|||
assert.strictEqual($carousel.find('.carousel-item.active').attr('id'), 'three', 'carousel wrapped around and slid from 1st to 3rd slide') |
|||
done() |
|||
}) |
|||
.bootstrapCarousel('prev') |
|||
}) |
|||
|
|||
QUnit.test('should stay at the end when the next method is called and wrap is false', function (assert) { |
|||
assert.expect(3) |
|||
var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="false">' |
|||
+ '<ol class="carousel-indicators">' |
|||
+ '<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' |
|||
+ '<li data-target="#carousel-example-generic" data-slide-to="1"/>' |
|||
+ '<li data-target="#carousel-example-generic" data-slide-to="2"/>' |
|||
+ '</ol>' |
|||
+ '<div class="carousel-inner">' |
|||
+ '<div class="carousel-item active" id="one">' |
|||
+ '<div class="carousel-caption"/>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item" id="two">' |
|||
+ '<div class="carousel-caption"/>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item" id="three">' |
|||
+ '<div class="carousel-caption"/>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<a class="left carousel-control" href="#carousel-example-generic" data-slide="prev"/>' |
|||
+ '<a class="right carousel-control" href="#carousel-example-generic" data-slide="next"/>' |
|||
+ '</div>' |
|||
var $carousel = $(carouselHTML) |
|||
var getActiveId = function () { return $carousel.find('.carousel-item.active').attr('id') } |
|||
|
|||
var done = assert.async() |
|||
|
|||
$carousel |
|||
.one('slid.bs.carousel', function () { |
|||
assert.strictEqual(getActiveId(), 'two', 'carousel slid from 1st to 2nd slide') |
|||
$carousel |
|||
.one('slid.bs.carousel', function () { |
|||
assert.strictEqual(getActiveId(), 'three', 'carousel slid from 2nd to 3rd slide') |
|||
$carousel |
|||
.one('slid.bs.carousel', function () { |
|||
assert.ok(false, 'carousel slid when it should not have slid') |
|||
}) |
|||
.bootstrapCarousel('next') |
|||
assert.strictEqual(getActiveId(), 'three', 'carousel did not wrap around and stayed on 3rd slide') |
|||
done() |
|||
}) |
|||
.bootstrapCarousel('next') |
|||
}) |
|||
.bootstrapCarousel('next') |
|||
}) |
|||
|
|||
QUnit.test('should stay at the start when the prev method is called and wrap is false', function (assert) { |
|||
assert.expect(1) |
|||
var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="false">' |
|||
+ '<ol class="carousel-indicators">' |
|||
+ '<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' |
|||
+ '<li data-target="#carousel-example-generic" data-slide-to="1"/>' |
|||
+ '<li data-target="#carousel-example-generic" data-slide-to="2"/>' |
|||
+ '</ol>' |
|||
+ '<div class="carousel-inner">' |
|||
+ '<div class="carousel-item active" id="one">' |
|||
+ '<div class="carousel-caption"/>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item" id="two">' |
|||
+ '<div class="carousel-caption"/>' |
|||
+ '</div>' |
|||
+ '<div class="carousel-item" id="three">' |
|||
+ '<div class="carousel-caption"/>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<a class="left carousel-control" href="#carousel-example-generic" data-slide="prev"/>' |
|||
+ '<a class="right carousel-control" href="#carousel-example-generic" data-slide="next"/>' |
|||
+ '</div>' |
|||
var $carousel = $(carouselHTML) |
|||
|
|||
$carousel |
|||
.on('slid.bs.carousel', function () { |
|||
assert.ok(false, 'carousel slid when it should not have slid') |
|||
}) |
|||
.bootstrapCarousel('prev') |
|||
assert.strictEqual($carousel.find('.carousel-item.active').attr('id'), 'one', 'carousel did not wrap around and stayed on 1st slide') |
|||
}) |
|||
|
|||
QUnit.test('should not prevent keydown for inputs and textareas', function (assert) { |
|||
assert.expect(2) |
|||
var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false">' |
|||
+ '<div class="carousel-inner">' |
|||
+ '<div id="first" class="carousel-item">' |
|||
+ '<input type="text" id="inputText" />' |
|||
+ '</div>' |
|||
+ '<div id="second" class="carousel-item active">' |
|||
+ '<textarea id="txtArea"></textarea>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
var $template = $(templateHTML) |
|||
var done = assert.async() |
|||
$template.appendTo('#qunit-fixture') |
|||
var $inputText = $template.find('#inputText') |
|||
var $textArea = $template.find('#txtArea') |
|||
$template.bootstrapCarousel() |
|||
|
|||
var eventKeyDown = $.Event('keydown', { which: 65 }) // 65 for "a"
|
|||
$inputText.on('keydown', function (event) { |
|||
assert.strictEqual(event.isDefaultPrevented(), false) |
|||
}) |
|||
$inputText.trigger(eventKeyDown) |
|||
|
|||
$textArea.on('keydown', function (event) { |
|||
assert.strictEqual(event.isDefaultPrevented(), false) |
|||
done() |
|||
}) |
|||
$textArea.trigger(eventKeyDown) |
|||
}) |
|||
}) |
@ -1,493 +0,0 @@ |
|||
$(function () { |
|||
'use strict' |
|||
|
|||
QUnit.module('collapse plugin') |
|||
|
|||
QUnit.test('should be defined on jquery object', function (assert) { |
|||
assert.expect(1) |
|||
assert.ok($(document.body).collapse, 'collapse method is defined') |
|||
}) |
|||
|
|||
QUnit.module('collapse', { |
|||
beforeEach: function () { |
|||
// Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
|
|||
$.fn.bootstrapCollapse = $.fn.collapse.noConflict() |
|||
}, |
|||
afterEach: function () { |
|||
$.fn.collapse = $.fn.bootstrapCollapse |
|||
delete $.fn.bootstrapCollapse |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should provide no conflict', function (assert) { |
|||
assert.expect(1) |
|||
assert.strictEqual($.fn.collapse, undefined, 'collapse was set back to undefined (org value)') |
|||
}) |
|||
|
|||
QUnit.test('should throw explicit error on undefined method', function (assert) { |
|||
assert.expect(1) |
|||
var $el = $('<div/>') |
|||
$el.bootstrapCollapse() |
|||
try { |
|||
$el.bootstrapCollapse('noMethod') |
|||
} |
|||
catch (err) { |
|||
assert.strictEqual(err.message, 'No method named "noMethod"') |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should return jquery collection containing the element', function (assert) { |
|||
assert.expect(2) |
|||
var $el = $('<div/>') |
|||
var $collapse = $el.bootstrapCollapse() |
|||
assert.ok($collapse instanceof $, 'returns jquery collection') |
|||
assert.strictEqual($collapse[0], $el[0], 'collection contains element') |
|||
}) |
|||
|
|||
QUnit.test('should show a collapsed element', function (assert) { |
|||
assert.expect(2) |
|||
var $el = $('<div class="collapse"/>').bootstrapCollapse('show') |
|||
|
|||
assert.ok($el.hasClass('show'), 'has class "show"') |
|||
assert.ok(!/height/i.test($el.attr('style')), 'has height reset') |
|||
}) |
|||
|
|||
QUnit.test('should collapse only the first collapse', function (assert) { |
|||
assert.expect(2) |
|||
var html = [ |
|||
'<div class="panel-group" id="accordion1">', |
|||
'<div class="panel">', |
|||
'<div id="collapse1" class="collapse"/>', |
|||
'</div>', |
|||
'</div>', |
|||
'<div class="panel-group" id="accordion2">', |
|||
'<div class="panel">', |
|||
'<div id="collapse2" class="collapse show"/>', |
|||
'</div>', |
|||
'</div>' |
|||
].join('') |
|||
$(html).appendTo('#qunit-fixture') |
|||
var $el1 = $('#collapse1') |
|||
var $el2 = $('#collapse2') |
|||
$el1.bootstrapCollapse('show') |
|||
|
|||
assert.ok($el1.hasClass('show')) |
|||
assert.ok($el2.hasClass('show')) |
|||
}) |
|||
|
|||
QUnit.test('should hide a collapsed element', function (assert) { |
|||
assert.expect(1) |
|||
var $el = $('<div class="collapse"/>').bootstrapCollapse('hide') |
|||
|
|||
assert.ok(!$el.hasClass('show'), 'does not have class "show"') |
|||
}) |
|||
|
|||
QUnit.test('should not fire shown when show is prevented', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
$('<div class="collapse"/>') |
|||
.on('show.bs.collapse', function (e) { |
|||
e.preventDefault() |
|||
assert.ok(true, 'show event fired') |
|||
done() |
|||
}) |
|||
.on('shown.bs.collapse', function () { |
|||
assert.ok(false, 'shown event fired') |
|||
}) |
|||
.bootstrapCollapse('show') |
|||
}) |
|||
|
|||
QUnit.test('should reset style to auto after finishing opening collapse', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
|
|||
$('<div class="collapse" style="height: 0px"/>') |
|||
.on('show.bs.collapse', function () { |
|||
assert.strictEqual(this.style.height, '0px', 'height is 0px') |
|||
}) |
|||
.on('shown.bs.collapse', function () { |
|||
assert.strictEqual(this.style.height, '', 'height is auto') |
|||
done() |
|||
}) |
|||
.bootstrapCollapse('show') |
|||
}) |
|||
|
|||
QUnit.test('should reset style to auto after finishing closing collapse', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
$('<div class="collapse"/>') |
|||
.on('shown.bs.collapse', function () { |
|||
$(this).bootstrapCollapse('hide') |
|||
}) |
|||
.on('hidden.bs.collapse', function () { |
|||
assert.strictEqual(this.style.height, '', 'height is auto') |
|||
done() |
|||
}) |
|||
.bootstrapCollapse('show') |
|||
}) |
|||
|
|||
QUnit.test('should remove "collapsed" class from target when collapse is shown', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
var $target = $('<a role="button" data-toggle="collapse" class="collapsed" href="#test1"/>').appendTo('#qunit-fixture') |
|||
|
|||
$('<div id="test1"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('shown.bs.collapse', function () { |
|||
assert.ok(!$target.hasClass('collapsed'), 'target does not have collapsed class') |
|||
done() |
|||
}) |
|||
|
|||
$target.trigger('click') |
|||
}) |
|||
|
|||
QUnit.test('should add "collapsed" class to target when collapse is hidden', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
var $target = $('<a role="button" data-toggle="collapse" href="#test1"/>').appendTo('#qunit-fixture') |
|||
|
|||
$('<div id="test1" class="show"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('hidden.bs.collapse', function () { |
|||
assert.ok($target.hasClass('collapsed'), 'target has collapsed class') |
|||
done() |
|||
}) |
|||
|
|||
$target.trigger('click') |
|||
}) |
|||
|
|||
QUnit.test('should remove "collapsed" class from all triggers targeting the collapse when the collapse is shown', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
|
|||
var $target = $('<a role="button" data-toggle="collapse" class="collapsed" href="#test1"/>').appendTo('#qunit-fixture') |
|||
var $alt = $('<a role="button" data-toggle="collapse" class="collapsed" href="#test1"/>').appendTo('#qunit-fixture') |
|||
|
|||
$('<div id="test1"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('shown.bs.collapse', function () { |
|||
assert.ok(!$target.hasClass('collapsed'), 'target trigger does not have collapsed class') |
|||
assert.ok(!$alt.hasClass('collapsed'), 'alt trigger does not have collapsed class') |
|||
done() |
|||
}) |
|||
|
|||
$target.trigger('click') |
|||
}) |
|||
|
|||
QUnit.test('should add "collapsed" class to all triggers targeting the collapse when the collapse is hidden', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
|
|||
var $target = $('<a role="button" data-toggle="collapse" href="#test1"/>').appendTo('#qunit-fixture') |
|||
var $alt = $('<a role="button" data-toggle="collapse" href="#test1"/>').appendTo('#qunit-fixture') |
|||
|
|||
$('<div id="test1" class="show"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('hidden.bs.collapse', function () { |
|||
assert.ok($target.hasClass('collapsed'), 'target has collapsed class') |
|||
assert.ok($alt.hasClass('collapsed'), 'alt trigger has collapsed class') |
|||
done() |
|||
}) |
|||
|
|||
$target.trigger('click') |
|||
}) |
|||
|
|||
QUnit.test('should not close a collapse when initialized with "show" option if already shown', function (assert) { |
|||
assert.expect(0) |
|||
var done = assert.async() |
|||
|
|||
var $test = $('<div id="test1" class="show"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('hide.bs.collapse', function () { |
|||
assert.ok(false) |
|||
}) |
|||
|
|||
$test.bootstrapCollapse('show') |
|||
|
|||
setTimeout(done, 0) |
|||
}) |
|||
|
|||
QUnit.test('should open a collapse when initialized with "show" option if not already shown', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
var $test = $('<div id="test1" />') |
|||
.appendTo('#qunit-fixture') |
|||
.on('show.bs.collapse', function () { |
|||
assert.ok(true) |
|||
}) |
|||
|
|||
$test.bootstrapCollapse('show') |
|||
|
|||
setTimeout(done, 0) |
|||
}) |
|||
|
|||
QUnit.test('should not show a collapse when initialized with "hide" option if already hidden', function (assert) { |
|||
assert.expect(0) |
|||
var done = assert.async() |
|||
|
|||
$('<div class="collapse"></div>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('show.bs.collapse', function () { |
|||
assert.ok(false, 'showing a previously-uninitialized hidden collapse when the "hide" method is called') |
|||
}) |
|||
.bootstrapCollapse('hide') |
|||
|
|||
setTimeout(done, 0) |
|||
}) |
|||
|
|||
QUnit.test('should hide a collapse when initialized with "hide" option if not already hidden', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
$('<div class="collapse show"></div>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('hide.bs.collapse', function () { |
|||
assert.ok(true, 'hiding a previously-uninitialized shown collapse when the "hide" method is called') |
|||
}) |
|||
.bootstrapCollapse('hide') |
|||
|
|||
setTimeout(done, 0) |
|||
}) |
|||
|
|||
QUnit.test('should remove "collapsed" class from active accordion target', function (assert) { |
|||
assert.expect(3) |
|||
var done = assert.async() |
|||
|
|||
var accordionHTML = '<div id="accordion">' |
|||
+ '<div class="card"/>' |
|||
+ '<div class="card"/>' |
|||
+ '<div class="card"/>' |
|||
+ '</div>' |
|||
var $groups = $(accordionHTML).appendTo('#qunit-fixture').find('.card') |
|||
|
|||
var $target1 = $('<a role="button" data-toggle="collapse" href="#body1" data-parent="#accordion"/>').appendTo($groups.eq(0)) |
|||
|
|||
$('<div id="body1" class="show"/>').appendTo($groups.eq(0)) |
|||
|
|||
var $target2 = $('<a class="collapsed" data-toggle="collapse" role="button" href="#body2" data-parent="#accordion"/>').appendTo($groups.eq(1)) |
|||
|
|||
$('<div id="body2"/>').appendTo($groups.eq(1)) |
|||
|
|||
var $target3 = $('<a class="collapsed" data-toggle="collapse" role="button" href="#body3" data-parent="#accordion"/>').appendTo($groups.eq(2)) |
|||
|
|||
$('<div id="body3"/>') |
|||
.appendTo($groups.eq(2)) |
|||
.on('shown.bs.collapse', function () { |
|||
assert.ok($target1.hasClass('collapsed'), 'inactive target 1 does have class "collapsed"') |
|||
assert.ok($target2.hasClass('collapsed'), 'inactive target 2 does have class "collapsed"') |
|||
assert.ok(!$target3.hasClass('collapsed'), 'active target 3 does not have class "collapsed"') |
|||
|
|||
done() |
|||
}) |
|||
|
|||
$target3.trigger('click') |
|||
}) |
|||
|
|||
QUnit.test('should allow dots in data-parent', function (assert) { |
|||
assert.expect(3) |
|||
var done = assert.async() |
|||
|
|||
var accordionHTML = '<div class="accordion">' |
|||
+ '<div class="card"/>' |
|||
+ '<div class="card"/>' |
|||
+ '<div class="card"/>' |
|||
+ '</div>' |
|||
var $groups = $(accordionHTML).appendTo('#qunit-fixture').find('.card') |
|||
|
|||
var $target1 = $('<a role="button" data-toggle="collapse" href="#body1" data-parent=".accordion"/>').appendTo($groups.eq(0)) |
|||
|
|||
$('<div id="body1" class="show"/>').appendTo($groups.eq(0)) |
|||
|
|||
var $target2 = $('<a class="collapsed" data-toggle="collapse" role="button" href="#body2" data-parent=".accordion"/>').appendTo($groups.eq(1)) |
|||
|
|||
$('<div id="body2"/>').appendTo($groups.eq(1)) |
|||
|
|||
var $target3 = $('<a class="collapsed" data-toggle="collapse" role="button" href="#body3" data-parent=".accordion"/>').appendTo($groups.eq(2)) |
|||
|
|||
$('<div id="body3"/>') |
|||
.appendTo($groups.eq(2)) |
|||
.on('shown.bs.collapse', function () { |
|||
assert.ok($target1.hasClass('collapsed'), 'inactive target 1 does have class "collapsed"') |
|||
assert.ok($target2.hasClass('collapsed'), 'inactive target 2 does have class "collapsed"') |
|||
assert.ok(!$target3.hasClass('collapsed'), 'active target 3 does not have class "collapsed"') |
|||
|
|||
done() |
|||
}) |
|||
|
|||
$target3.trigger('click') |
|||
}) |
|||
|
|||
QUnit.test('should set aria-expanded="true" on target when collapse is shown', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
var $target = $('<a role="button" data-toggle="collapse" class="collapsed" href="#test1" aria-expanded="false"/>').appendTo('#qunit-fixture') |
|||
|
|||
$('<div id="test1"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('shown.bs.collapse', function () { |
|||
assert.strictEqual($target.attr('aria-expanded'), 'true', 'aria-expanded on target is "true"') |
|||
done() |
|||
}) |
|||
|
|||
$target.trigger('click') |
|||
}) |
|||
|
|||
QUnit.test('should set aria-expanded="false" on target when collapse is hidden', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
var $target = $('<a role="button" data-toggle="collapse" href="#test1" aria-expanded="true"/>').appendTo('#qunit-fixture') |
|||
|
|||
$('<div id="test1" class="show"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('hidden.bs.collapse', function () { |
|||
assert.strictEqual($target.attr('aria-expanded'), 'false', 'aria-expanded on target is "false"') |
|||
done() |
|||
}) |
|||
|
|||
$target.trigger('click') |
|||
}) |
|||
|
|||
QUnit.test('should set aria-expanded="true" on all triggers targeting the collapse when the collapse is shown', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
|
|||
var $target = $('<a role="button" data-toggle="collapse" class="collapsed" href="#test1" aria-expanded="false"/>').appendTo('#qunit-fixture') |
|||
var $alt = $('<a role="button" data-toggle="collapse" class="collapsed" href="#test1" aria-expanded="false"/>').appendTo('#qunit-fixture') |
|||
|
|||
$('<div id="test1"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('shown.bs.collapse', function () { |
|||
assert.strictEqual($target.attr('aria-expanded'), 'true', 'aria-expanded on target is "true"') |
|||
assert.strictEqual($alt.attr('aria-expanded'), 'true', 'aria-expanded on alt is "true"') |
|||
done() |
|||
}) |
|||
|
|||
$target.trigger('click') |
|||
}) |
|||
|
|||
QUnit.test('should set aria-expanded="false" on all triggers targeting the collapse when the collapse is hidden', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
|
|||
var $target = $('<a role="button" data-toggle="collapse" href="#test1" aria-expanded="true"/>').appendTo('#qunit-fixture') |
|||
var $alt = $('<a role="button" data-toggle="collapse" href="#test1" aria-expanded="true"/>').appendTo('#qunit-fixture') |
|||
|
|||
$('<div id="test1" class="show"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('hidden.bs.collapse', function () { |
|||
assert.strictEqual($target.attr('aria-expanded'), 'false', 'aria-expanded on target is "false"') |
|||
assert.strictEqual($alt.attr('aria-expanded'), 'false', 'aria-expanded on alt is "false"') |
|||
done() |
|||
}) |
|||
|
|||
$target.trigger('click') |
|||
}) |
|||
|
|||
QUnit.test('should change aria-expanded from active accordion target to "false" and set the newly active one to "true"', function (assert) { |
|||
assert.expect(3) |
|||
var done = assert.async() |
|||
|
|||
var accordionHTML = '<div id="accordion">' |
|||
+ '<div class="card"/>' |
|||
+ '<div class="card"/>' |
|||
+ '<div class="card"/>' |
|||
+ '</div>' |
|||
var $groups = $(accordionHTML).appendTo('#qunit-fixture').find('.card') |
|||
|
|||
var $target1 = $('<a role="button" data-toggle="collapse" href="#body1" data-parent="#accordion"/>').appendTo($groups.eq(0)) |
|||
|
|||
$('<div id="body1" aria-expanded="true" class="show"/>').appendTo($groups.eq(0)) |
|||
|
|||
var $target2 = $('<a role="button" data-toggle="collapse" href="#body2" data-parent="#accordion" class="collapsed" />').appendTo($groups.eq(1)) |
|||
|
|||
$('<div id="body2" aria-expanded="false"/>').appendTo($groups.eq(1)) |
|||
|
|||
var $target3 = $('<a class="collapsed" data-toggle="collapse" role="button" href="#body3" data-parent="#accordion"/>').appendTo($groups.eq(2)) |
|||
|
|||
$('<div id="body3" aria-expanded="false"/>') |
|||
.appendTo($groups.eq(2)) |
|||
.on('shown.bs.collapse', function () { |
|||
assert.strictEqual($target1.attr('aria-expanded'), 'false', 'inactive target 1 has aria-expanded="false"') |
|||
assert.strictEqual($target2.attr('aria-expanded'), 'false', 'inactive target 2 has aria-expanded="false"') |
|||
assert.strictEqual($target3.attr('aria-expanded'), 'true', 'active target 3 has aria-expanded="false"') |
|||
|
|||
done() |
|||
}) |
|||
|
|||
$target3.trigger('click') |
|||
}) |
|||
|
|||
QUnit.test('should not fire show event if show is prevented because other element is still transitioning', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
var accordionHTML = '<div id="accordion">' |
|||
+ '<div class="card"/>' |
|||
+ '<div class="card"/>' |
|||
+ '</div>' |
|||
var showFired = false |
|||
var $groups = $(accordionHTML).appendTo('#qunit-fixture').find('.card') |
|||
|
|||
var $target1 = $('<a role="button" data-toggle="collapse" href="#body1" data-parent="#accordion"/>').appendTo($groups.eq(0)) |
|||
|
|||
$('<div id="body1" class="collapse"/>') |
|||
.appendTo($groups.eq(0)) |
|||
.on('show.bs.collapse', function () { |
|||
showFired = true |
|||
}) |
|||
|
|||
var $target2 = $('<a role="button" data-toggle="collapse" href="#body2" data-parent="#accordion"/>').appendTo($groups.eq(1)) |
|||
var $body2 = $('<div id="body2" class="collapse"/>').appendTo($groups.eq(1)) |
|||
|
|||
$target2.trigger('click') |
|||
|
|||
$body2 |
|||
.toggleClass('show collapsing') |
|||
.data('bs.collapse')._isTransitioning = 1 |
|||
|
|||
$target1.trigger('click') |
|||
|
|||
setTimeout(function () { |
|||
assert.ok(!showFired, 'show event did not fire') |
|||
done() |
|||
}, 1) |
|||
}) |
|||
|
|||
QUnit.test('should add "collapsed" class to target when collapse is hidden via manual invocation', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
var $target = $('<a role="button" data-toggle="collapse" href="#test1"/>').appendTo('#qunit-fixture') |
|||
|
|||
$('<div id="test1" class="show"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('hidden.bs.collapse', function () { |
|||
assert.ok($target.hasClass('collapsed')) |
|||
done() |
|||
}) |
|||
.bootstrapCollapse('hide') |
|||
}) |
|||
|
|||
QUnit.test('should remove "collapsed" class from target when collapse is shown via manual invocation', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
var $target = $('<a role="button" data-toggle="collapse" class="collapsed" href="#test1"/>').appendTo('#qunit-fixture') |
|||
|
|||
$('<div id="test1"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('shown.bs.collapse', function () { |
|||
assert.ok(!$target.hasClass('collapsed')) |
|||
done() |
|||
}) |
|||
.bootstrapCollapse('show') |
|||
}) |
|||
|
|||
}) |
@ -1,495 +0,0 @@ |
|||
$(function () { |
|||
'use strict' |
|||
|
|||
QUnit.module('dropdowns plugin') |
|||
|
|||
QUnit.test('should be defined on jquery object', function (assert) { |
|||
assert.expect(1) |
|||
assert.ok($(document.body).dropdown, 'dropdown method is defined') |
|||
}) |
|||
|
|||
QUnit.module('dropdowns', { |
|||
beforeEach: function () { |
|||
// Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
|
|||
$.fn.bootstrapDropdown = $.fn.dropdown.noConflict() |
|||
}, |
|||
afterEach: function () { |
|||
$.fn.dropdown = $.fn.bootstrapDropdown |
|||
delete $.fn.bootstrapDropdown |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should provide no conflict', function (assert) { |
|||
assert.expect(1) |
|||
assert.strictEqual($.fn.dropdown, undefined, 'dropdown was set back to undefined (org value)') |
|||
}) |
|||
|
|||
QUnit.test('should throw explicit error on undefined method', function (assert) { |
|||
assert.expect(1) |
|||
var $el = $('<div/>') |
|||
$el.bootstrapDropdown() |
|||
try { |
|||
$el.bootstrapDropdown('noMethod') |
|||
} |
|||
catch (err) { |
|||
assert.strictEqual(err.message, 'No method named "noMethod"') |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should return jquery collection containing the element', function (assert) { |
|||
assert.expect(2) |
|||
var $el = $('<div/>') |
|||
var $dropdown = $el.bootstrapDropdown() |
|||
assert.ok($dropdown instanceof $, 'returns jquery collection') |
|||
assert.strictEqual($dropdown[0], $el[0], 'collection contains element') |
|||
}) |
|||
|
|||
QUnit.test('should not open dropdown if target is disabled via attribute', function (assert) { |
|||
assert.expect(1) |
|||
var dropdownHTML = '<ul class="tabs">' |
|||
+ '<li class="dropdown">' |
|||
+ '<button disabled href="#" class="btn dropdown-toggle" data-toggle="dropdown">Dropdown</button>' |
|||
+ '<ul class="dropdown-menu">' |
|||
+ '<li><a href="#">Secondary link</a></li>' |
|||
+ '<li><a href="#">Something else here</a></li>' |
|||
+ '<li class="divider"/>' |
|||
+ '<li><a href="#">Another link</a></li>' |
|||
+ '</ul>' |
|||
+ '</li>' |
|||
+ '</ul>' |
|||
var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown().trigger('click') |
|||
|
|||
assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click') |
|||
}) |
|||
|
|||
QUnit.test('should set aria-expanded="true" on target when dropdown menu is shown', function (assert) { |
|||
assert.expect(1) |
|||
var dropdownHTML = '<ul class="tabs">' |
|||
+ '<li class="dropdown">' |
|||
+ '<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">Dropdown</a>' |
|||
+ '<ul class="dropdown-menu">' |
|||
+ '<li><a href="#">Secondary link</a></li>' |
|||
+ '<li><a href="#">Something else here</a></li>' |
|||
+ '<li class="divider"/>' |
|||
+ '<li><a href="#">Another link</a></li>' |
|||
+ '</ul>' |
|||
+ '</li>' |
|||
+ '</ul>' |
|||
var $dropdown = $(dropdownHTML) |
|||
.find('[data-toggle="dropdown"]') |
|||
.bootstrapDropdown() |
|||
.trigger('click') |
|||
|
|||
assert.strictEqual($dropdown.attr('aria-expanded'), 'true', 'aria-expanded is set to string "true" on click') |
|||
}) |
|||
|
|||
QUnit.test('should set aria-expanded="false" on target when dropdown menu is hidden', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
var dropdownHTML = '<ul class="tabs">' |
|||
+ '<li class="dropdown">' |
|||
+ '<a href="#" class="dropdown-toggle" aria-expanded="false" data-toggle="dropdown">Dropdown</a>' |
|||
+ '<ul class="dropdown-menu">' |
|||
+ '<li><a href="#">Secondary link</a></li>' |
|||
+ '<li><a href="#">Something else here</a></li>' |
|||
+ '<li class="divider"/>' |
|||
+ '<li><a href="#">Another link</a></li>' |
|||
+ '</ul>' |
|||
+ '</li>' |
|||
+ '</ul>' |
|||
var $dropdown = $(dropdownHTML) |
|||
.appendTo('#qunit-fixture') |
|||
.find('[data-toggle="dropdown"]') |
|||
.bootstrapDropdown() |
|||
|
|||
$dropdown |
|||
.parent('.dropdown') |
|||
.on('hidden.bs.dropdown', function () { |
|||
assert.strictEqual($dropdown.attr('aria-expanded'), 'false', 'aria-expanded is set to string "false" on hide') |
|||
done() |
|||
}) |
|||
|
|||
$dropdown.trigger('click') |
|||
$(document.body).trigger('click') |
|||
}) |
|||
|
|||
QUnit.test('should not open dropdown if target is disabled via class', function (assert) { |
|||
assert.expect(1) |
|||
var dropdownHTML = '<ul class="tabs">' |
|||
+ '<li class="dropdown">' |
|||
+ '<button href="#" class="btn dropdown-toggle disabled" data-toggle="dropdown">Dropdown</button>' |
|||
+ '<ul class="dropdown-menu">' |
|||
+ '<li><a href="#">Secondary link</a></li>' |
|||
+ '<li><a href="#">Something else here</a></li>' |
|||
+ '<li class="divider"/>' |
|||
+ '<li><a href="#">Another link</a></li>' |
|||
+ '</ul>' |
|||
+ '</li>' |
|||
+ '</ul>' |
|||
var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown().trigger('click') |
|||
|
|||
assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click') |
|||
}) |
|||
|
|||
QUnit.test('should add class show to menu if clicked', function (assert) { |
|||
assert.expect(1) |
|||
var dropdownHTML = '<ul class="tabs">' |
|||
+ '<li class="dropdown">' |
|||
+ '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' |
|||
+ '<ul class="dropdown-menu">' |
|||
+ '<li><a href="#">Secondary link</a></li>' |
|||
+ '<li><a href="#">Something else here</a></li>' |
|||
+ '<li class="divider"/>' |
|||
+ '<li><a href="#">Another link</a></li>' |
|||
+ '</ul>' |
|||
+ '</li>' |
|||
+ '</ul>' |
|||
var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown().trigger('click') |
|||
|
|||
assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click') |
|||
}) |
|||
|
|||
QUnit.test('should test if element has a # before assuming it\'s a selector', function (assert) { |
|||
assert.expect(1) |
|||
var dropdownHTML = '<ul class="tabs">' |
|||
+ '<li class="dropdown">' |
|||
+ '<a href="/foo/" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' |
|||
+ '<ul class="dropdown-menu">' |
|||
+ '<li><a href="#">Secondary link</a></li>' |
|||
+ '<li><a href="#">Something else here</a></li>' |
|||
+ '<li class="divider"/>' |
|||
+ '<li><a href="#">Another link</a></li>' |
|||
+ '</ul>' |
|||
+ '</li>' |
|||
+ '</ul>' |
|||
var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown().trigger('click') |
|||
|
|||
assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click') |
|||
}) |
|||
|
|||
|
|||
QUnit.test('should remove "show" class if body is clicked', function (assert) { |
|||
assert.expect(2) |
|||
var dropdownHTML = '<ul class="tabs">' |
|||
+ '<li class="dropdown">' |
|||
+ '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' |
|||
+ '<ul class="dropdown-menu">' |
|||
+ '<li><a href="#">Secondary link</a></li>' |
|||
+ '<li><a href="#">Something else here</a></li>' |
|||
+ '<li class="divider"/>' |
|||
+ '<li><a href="#">Another link</a></li>' |
|||
+ '</ul>' |
|||
+ '</li>' |
|||
+ '</ul>' |
|||
var $dropdown = $(dropdownHTML) |
|||
.appendTo('#qunit-fixture') |
|||
.find('[data-toggle="dropdown"]') |
|||
.bootstrapDropdown() |
|||
.trigger('click') |
|||
|
|||
assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click') |
|||
$(document.body).trigger('click') |
|||
assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), '"show" class removed') |
|||
}) |
|||
|
|||
QUnit.test('should remove "show" class if body is focused', function (assert) { |
|||
assert.expect(2) |
|||
var dropdownHTML = '<div class="tabs">' |
|||
+ '<div class="dropdown">' |
|||
+ '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' |
|||
+ '<div class="dropdown-menu">' |
|||
+ '<a class="dropdown-item" href="#">Secondary link</a>' |
|||
+ '<a class="dropdown-item" href="#">Something else here</a>' |
|||
+ '<div class="dropdown-divider"/>' |
|||
+ '<a class="dropdown-item" href="#">Another link</a>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
var $dropdown = $(dropdownHTML) |
|||
.appendTo('#qunit-fixture') |
|||
.find('[data-toggle="dropdown"]') |
|||
.bootstrapDropdown() |
|||
.trigger('click') |
|||
|
|||
assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click') |
|||
$(document.body).trigger('focusin') |
|||
assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), '"show" class removed') |
|||
}) |
|||
|
|||
QUnit.test('should remove "show" class if body is clicked, with multiple dropdowns', function (assert) { |
|||
assert.expect(7) |
|||
var dropdownHTML = '<ul class="nav">' |
|||
+ '<li><a href="#menu1">Menu 1</a></li>' |
|||
+ '<li class="dropdown" id="testmenu">' |
|||
+ '<a class="dropdown-toggle" data-toggle="dropdown" href="#testmenu">Test menu <span class="caret"/></a>' |
|||
+ '<ul class="dropdown-menu">' |
|||
+ '<li><a href="#sub1">Submenu 1</a></li>' |
|||
+ '</ul>' |
|||
+ '</li>' |
|||
+ '</ul>' |
|||
+ '<div class="btn-group">' |
|||
+ '<button class="btn">Actions</button>' |
|||
+ '<button class="btn dropdown-toggle" data-toggle="dropdown"><span class="caret"/></button>' |
|||
+ '<ul class="dropdown-menu">' |
|||
+ '<li><a href="#">Action 1</a></li>' |
|||
+ '</ul>' |
|||
+ '</div>' |
|||
var $dropdowns = $(dropdownHTML).appendTo('#qunit-fixture').find('[data-toggle="dropdown"]') |
|||
var $first = $dropdowns.first() |
|||
var $last = $dropdowns.last() |
|||
|
|||
assert.strictEqual($dropdowns.length, 2, 'two dropdowns') |
|||
|
|||
$first.trigger('click') |
|||
assert.strictEqual($first.parents('.show').length, 1, '"show" class added on click') |
|||
assert.strictEqual($('#qunit-fixture .show').length, 1, 'only one dropdown is shown') |
|||
$(document.body).trigger('click') |
|||
assert.strictEqual($('#qunit-fixture .show').length, 0, '"show" class removed') |
|||
|
|||
$last.trigger('click') |
|||
assert.strictEqual($last.parent('.show').length, 1, '"show" class added on click') |
|||
assert.strictEqual($('#qunit-fixture .show').length, 1, 'only one dropdown is shown') |
|||
$(document.body).trigger('click') |
|||
assert.strictEqual($('#qunit-fixture .show').length, 0, '"show" class removed') |
|||
}) |
|||
|
|||
QUnit.test('should remove "show" class if body is focused, with multiple dropdowns', function (assert) { |
|||
assert.expect(7) |
|||
var dropdownHTML = '<div class="nav">' |
|||
+ '<div class="dropdown" id="testmenu">' |
|||
+ '<a class="dropdown-toggle" data-toggle="dropdown" href="#testmenu">Test menu <span class="caret"/></a>' |
|||
+ '<div class="dropdown-menu">' |
|||
+ '<a class="dropdown-item" href="#sub1">Submenu 1</a>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<div class="btn-group">' |
|||
+ '<button class="btn">Actions</button>' |
|||
+ '<button class="btn dropdown-toggle" data-toggle="dropdown"><span class="caret"/></button>' |
|||
+ '<div class="dropdown-menu">' |
|||
+ '<a class="dropdown-item" href="#">Action 1</a>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
var $dropdowns = $(dropdownHTML).appendTo('#qunit-fixture').find('[data-toggle="dropdown"]') |
|||
var $first = $dropdowns.first() |
|||
var $last = $dropdowns.last() |
|||
|
|||
assert.strictEqual($dropdowns.length, 2, 'two dropdowns') |
|||
|
|||
$first.trigger('click') |
|||
assert.strictEqual($first.parents('.show').length, 1, '"show" class added on click') |
|||
assert.strictEqual($('#qunit-fixture .show').length, 1, 'only one dropdown is show') |
|||
$(document.body).trigger('focusin') |
|||
assert.strictEqual($('#qunit-fixture .show').length, 0, '"show" class removed') |
|||
|
|||
$last.trigger('click') |
|||
assert.strictEqual($last.parent('.show').length, 1, '"show" class added on click') |
|||
assert.strictEqual($('#qunit-fixture .show').length, 1, 'only one dropdown is show') |
|||
$(document.body).trigger('focusin') |
|||
assert.strictEqual($('#qunit-fixture .show').length, 0, '"show" class removed') |
|||
}) |
|||
|
|||
QUnit.test('should fire show and hide event', function (assert) { |
|||
assert.expect(2) |
|||
var dropdownHTML = '<ul class="tabs">' |
|||
+ '<li class="dropdown">' |
|||
+ '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' |
|||
+ '<ul class="dropdown-menu">' |
|||
+ '<li><a href="#">Secondary link</a></li>' |
|||
+ '<li><a href="#">Something else here</a></li>' |
|||
+ '<li class="divider"/>' |
|||
+ '<li><a href="#">Another link</a></li>' |
|||
+ '</ul>' |
|||
+ '</li>' |
|||
+ '</ul>' |
|||
var $dropdown = $(dropdownHTML) |
|||
.appendTo('#qunit-fixture') |
|||
.find('[data-toggle="dropdown"]') |
|||
.bootstrapDropdown() |
|||
|
|||
var done = assert.async() |
|||
|
|||
$dropdown |
|||
.parent('.dropdown') |
|||
.on('show.bs.dropdown', function () { |
|||
assert.ok(true, 'show was fired') |
|||
}) |
|||
.on('hide.bs.dropdown', function () { |
|||
assert.ok(true, 'hide was fired') |
|||
done() |
|||
}) |
|||
|
|||
$dropdown.trigger('click') |
|||
$(document.body).trigger('click') |
|||
}) |
|||
|
|||
|
|||
QUnit.test('should fire shown and hidden event', function (assert) { |
|||
assert.expect(2) |
|||
var dropdownHTML = '<ul class="tabs">' |
|||
+ '<li class="dropdown">' |
|||
+ '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' |
|||
+ '<ul class="dropdown-menu">' |
|||
+ '<li><a href="#">Secondary link</a></li>' |
|||
+ '<li><a href="#">Something else here</a></li>' |
|||
+ '<li class="divider"/>' |
|||
+ '<li><a href="#">Another link</a></li>' |
|||
+ '</ul>' |
|||
+ '</li>' |
|||
+ '</ul>' |
|||
var $dropdown = $(dropdownHTML) |
|||
.appendTo('#qunit-fixture') |
|||
.find('[data-toggle="dropdown"]') |
|||
.bootstrapDropdown() |
|||
|
|||
var done = assert.async() |
|||
|
|||
$dropdown |
|||
.parent('.dropdown') |
|||
.on('shown.bs.dropdown', function () { |
|||
assert.ok(true, 'shown was fired') |
|||
}) |
|||
.on('hidden.bs.dropdown', function () { |
|||
assert.ok(true, 'hidden was fired') |
|||
done() |
|||
}) |
|||
|
|||
$dropdown.trigger('click') |
|||
$(document.body).trigger('click') |
|||
}) |
|||
|
|||
QUnit.test('should fire shown and hidden event with a relatedTarget', function (assert) { |
|||
assert.expect(2) |
|||
var dropdownHTML = '<ul class="tabs">' |
|||
+ '<li class="dropdown">' |
|||
+ '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' |
|||
+ '<ul class="dropdown-menu">' |
|||
+ '<li><a href="#">Secondary link</a></li>' |
|||
+ '<li><a href="#">Something else here</a></li>' |
|||
+ '<li class="divider"/>' |
|||
+ '<li><a href="#">Another link</a></li>' |
|||
+ '</ul>' |
|||
+ '</li>' |
|||
+ '</ul>' |
|||
var $dropdown = $(dropdownHTML) |
|||
.appendTo('#qunit-fixture') |
|||
.find('[data-toggle="dropdown"]') |
|||
.bootstrapDropdown() |
|||
var done = assert.async() |
|||
|
|||
$dropdown.parent('.dropdown') |
|||
.on('hidden.bs.dropdown', function (e) { |
|||
assert.strictEqual(e.relatedTarget, $dropdown[0]) |
|||
done() |
|||
}) |
|||
.on('shown.bs.dropdown', function (e) { |
|||
assert.strictEqual(e.relatedTarget, $dropdown[0]) |
|||
$(document.body).trigger('click') |
|||
}) |
|||
|
|||
$dropdown.trigger('click') |
|||
}) |
|||
|
|||
QUnit.test('should ignore keyboard events within <input>s and <textarea>s', function (assert) { |
|||
assert.expect(3) |
|||
var done = assert.async() |
|||
|
|||
var dropdownHTML = '<ul class="tabs">' |
|||
+ '<li class="dropdown">' |
|||
+ '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' |
|||
+ '<ul class="dropdown-menu">' |
|||
+ '<li><a href="#">Secondary link</a></li>' |
|||
+ '<li><a href="#">Something else here</a></li>' |
|||
+ '<li class="divider"/>' |
|||
+ '<li><a href="#">Another link</a></li>' |
|||
+ '<li><input type="text" id="input"></li>' |
|||
+ '<li><textarea id="textarea"/></li>' |
|||
+ '</ul>' |
|||
+ '</li>' |
|||
+ '</ul>' |
|||
var $dropdown = $(dropdownHTML) |
|||
.appendTo('#qunit-fixture') |
|||
.find('[data-toggle="dropdown"]') |
|||
.bootstrapDropdown() |
|||
|
|||
var $input = $('#input') |
|||
var $textarea = $('#textarea') |
|||
|
|||
$dropdown |
|||
.parent('.dropdown') |
|||
.on('shown.bs.dropdown', function () { |
|||
assert.ok(true, 'shown was fired') |
|||
|
|||
$input.trigger('focus').trigger($.Event('keydown', { which: 38 })) |
|||
assert.ok($(document.activeElement).is($input), 'input still focused') |
|||
|
|||
$textarea.trigger('focus').trigger($.Event('keydown', { which: 38 })) |
|||
assert.ok($(document.activeElement).is($textarea), 'textarea still focused') |
|||
|
|||
done() |
|||
}) |
|||
|
|||
$dropdown.trigger('click') |
|||
}) |
|||
|
|||
QUnit.test('should skip disabled element when using keyboard navigation', function (assert) { |
|||
assert.expect(1) |
|||
var dropdownHTML = '<ul class="tabs">' |
|||
+ '<li class="dropdown">' |
|||
+ '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' |
|||
+ '<ul class="dropdown-menu">' |
|||
+ '<li class="disabled"><a href="#">Disabled link</a></li>' |
|||
+ '<li><a href="#">Another link</a></li>' |
|||
+ '</ul>' |
|||
+ '</li>' |
|||
+ '</ul>' |
|||
var $dropdown = $(dropdownHTML) |
|||
.appendTo('#qunit-fixture') |
|||
.find('[data-toggle="dropdown"]') |
|||
.bootstrapDropdown() |
|||
.trigger('click') |
|||
|
|||
$dropdown.trigger($.Event('keydown', { which: 40 })) |
|||
$dropdown.trigger($.Event('keydown', { which: 40 })) |
|||
|
|||
assert.ok(!$(document.activeElement).parent().is('.disabled'), '.disabled is not focused') |
|||
}) |
|||
|
|||
QUnit.test('should not close the dropdown if the user clicks on a text field', function (assert) { |
|||
assert.expect(1) |
|||
var dropdownHTML = '<div class="btn-group">' |
|||
+ '<button type="button" data-toggle="dropdown">Dropdown</button>' |
|||
+ '<ul class="dropdown-menu">' |
|||
+ '<li><input id="textField" type="text" /></li>' |
|||
+ '</ul>' |
|||
+ '</div>' |
|||
var $dropdown = $(dropdownHTML) |
|||
.appendTo('#qunit-fixture') |
|||
.find('[data-toggle="dropdown"]') |
|||
.bootstrapDropdown() |
|||
.trigger('click') |
|||
|
|||
$('#textField').trigger('click') |
|||
|
|||
assert.ok($dropdown.parent('.btn-group').hasClass('show'), 'dropdown menu is shown') |
|||
}) |
|||
|
|||
QUnit.test('should not close the dropdown if the user clicks on a textarea', function (assert) { |
|||
assert.expect(1) |
|||
var dropdownHTML = '<div class="btn-group">' |
|||
+ '<button type="button" data-toggle="dropdown">Dropdown</button>' |
|||
+ '<ul class="dropdown-menu">' |
|||
+ '<li><textarea id="textArea"></textarea></li>' |
|||
+ '</ul>' |
|||
+ '</div>' |
|||
var $dropdown = $(dropdownHTML) |
|||
.appendTo('#qunit-fixture') |
|||
.find('[data-toggle="dropdown"]') |
|||
.bootstrapDropdown() |
|||
.trigger('click') |
|||
|
|||
$('#textArea').trigger('click') |
|||
|
|||
assert.ok($dropdown.parent('.btn-group').hasClass('show'), 'dropdown menu is shown') |
|||
}) |
|||
}) |
@ -1,479 +0,0 @@ |
|||
$(function () { |
|||
'use strict' |
|||
|
|||
QUnit.module('modal plugin') |
|||
|
|||
QUnit.test('should be defined on jquery object', function (assert) { |
|||
assert.expect(1) |
|||
assert.ok($(document.body).modal, 'modal method is defined') |
|||
}) |
|||
|
|||
QUnit.module('modal', { |
|||
beforeEach: function () { |
|||
// Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
|
|||
$.fn.bootstrapModal = $.fn.modal.noConflict() |
|||
}, |
|||
afterEach: function () { |
|||
$.fn.modal = $.fn.bootstrapModal |
|||
delete $.fn.bootstrapModal |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should provide no conflict', function (assert) { |
|||
assert.expect(1) |
|||
assert.strictEqual($.fn.modal, undefined, 'modal was set back to undefined (orig value)') |
|||
}) |
|||
|
|||
QUnit.test('should throw explicit error on undefined method', function (assert) { |
|||
assert.expect(1) |
|||
var $el = $('<div id="modal-test"/>') |
|||
$el.bootstrapModal() |
|||
try { |
|||
$el.bootstrapModal('noMethod') |
|||
} |
|||
catch (err) { |
|||
assert.strictEqual(err.message, 'No method named "noMethod"') |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should return jquery collection containing the element', function (assert) { |
|||
assert.expect(2) |
|||
var $el = $('<div id="modal-test"/>') |
|||
var $modal = $el.bootstrapModal() |
|||
assert.ok($modal instanceof $, 'returns jquery collection') |
|||
assert.strictEqual($modal[0], $el[0], 'collection contains element') |
|||
}) |
|||
|
|||
QUnit.test('should expose defaults var for settings', function (assert) { |
|||
assert.expect(1) |
|||
assert.ok($.fn.bootstrapModal.Constructor.Default, 'default object exposed') |
|||
}) |
|||
|
|||
QUnit.test('should insert into dom when show method is called', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
$('<div id="modal-test"/>') |
|||
.on('shown.bs.modal', function () { |
|||
assert.notEqual($('#modal-test').length, 0, 'modal inserted into dom') |
|||
done() |
|||
}) |
|||
.bootstrapModal('show') |
|||
}) |
|||
|
|||
QUnit.test('should fire show event', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
$('<div id="modal-test"/>') |
|||
.on('show.bs.modal', function () { |
|||
assert.ok(true, 'show event fired') |
|||
done() |
|||
}) |
|||
.bootstrapModal('show') |
|||
}) |
|||
|
|||
QUnit.test('should not fire shown when show was prevented', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
$('<div id="modal-test"/>') |
|||
.on('show.bs.modal', function (e) { |
|||
e.preventDefault() |
|||
assert.ok(true, 'show event fired') |
|||
done() |
|||
}) |
|||
.on('shown.bs.modal', function () { |
|||
assert.ok(false, 'shown event fired') |
|||
}) |
|||
.bootstrapModal('show') |
|||
}) |
|||
|
|||
QUnit.test('should hide modal when hide is called', function (assert) { |
|||
assert.expect(3) |
|||
var done = assert.async() |
|||
|
|||
$('<div id="modal-test"/>') |
|||
.on('shown.bs.modal', function () { |
|||
assert.ok($('#modal-test').is(':visible'), 'modal visible') |
|||
assert.notEqual($('#modal-test').length, 0, 'modal inserted into dom') |
|||
$(this).bootstrapModal('hide') |
|||
}) |
|||
.on('hidden.bs.modal', function () { |
|||
assert.ok(!$('#modal-test').is(':visible'), 'modal hidden') |
|||
done() |
|||
}) |
|||
.bootstrapModal('show') |
|||
}) |
|||
|
|||
QUnit.test('should toggle when toggle is called', function (assert) { |
|||
assert.expect(3) |
|||
var done = assert.async() |
|||
|
|||
$('<div id="modal-test"/>') |
|||
.on('shown.bs.modal', function () { |
|||
assert.ok($('#modal-test').is(':visible'), 'modal visible') |
|||
assert.notEqual($('#modal-test').length, 0, 'modal inserted into dom') |
|||
$(this).bootstrapModal('toggle') |
|||
}) |
|||
.on('hidden.bs.modal', function () { |
|||
assert.ok(!$('#modal-test').is(':visible'), 'modal hidden') |
|||
done() |
|||
}) |
|||
.bootstrapModal('toggle') |
|||
}) |
|||
|
|||
QUnit.test('should remove from dom when click [data-dismiss="modal"]', function (assert) { |
|||
assert.expect(3) |
|||
var done = assert.async() |
|||
|
|||
$('<div id="modal-test"><span class="close" data-dismiss="modal"/></div>') |
|||
.on('shown.bs.modal', function () { |
|||
assert.ok($('#modal-test').is(':visible'), 'modal visible') |
|||
assert.notEqual($('#modal-test').length, 0, 'modal inserted into dom') |
|||
$(this).find('.close').trigger('click') |
|||
}) |
|||
.on('hidden.bs.modal', function () { |
|||
assert.ok(!$('#modal-test').is(':visible'), 'modal hidden') |
|||
done() |
|||
}) |
|||
.bootstrapModal('toggle') |
|||
}) |
|||
|
|||
QUnit.test('should allow modal close with "backdrop:false"', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
|
|||
$('<div id="modal-test" data-backdrop="false"/>') |
|||
.on('shown.bs.modal', function () { |
|||
assert.ok($('#modal-test').is(':visible'), 'modal visible') |
|||
$(this).bootstrapModal('hide') |
|||
}) |
|||
.on('hidden.bs.modal', function () { |
|||
assert.ok(!$('#modal-test').is(':visible'), 'modal hidden') |
|||
done() |
|||
}) |
|||
.bootstrapModal('show') |
|||
}) |
|||
|
|||
QUnit.test('should close modal when clicking outside of modal-content', function (assert) { |
|||
assert.expect(3) |
|||
var done = assert.async() |
|||
|
|||
$('<div id="modal-test"><div class="contents"/></div>') |
|||
.on('shown.bs.modal', function () { |
|||
assert.notEqual($('#modal-test').length, 0, 'modal inserted into dom') |
|||
$('.contents').trigger('click') |
|||
assert.ok($('#modal-test').is(':visible'), 'modal visible') |
|||
$('#modal-test').trigger('click') |
|||
}) |
|||
.on('hidden.bs.modal', function () { |
|||
assert.ok(!$('#modal-test').is(':visible'), 'modal hidden') |
|||
done() |
|||
}) |
|||
.bootstrapModal('show') |
|||
}) |
|||
|
|||
QUnit.test('should not close modal when clicking outside of modal-content if data-backdrop="true"', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
$('<div id="modal-test" data-backdrop="false"><div class="contents"/></div>') |
|||
.on('shown.bs.modal', function () { |
|||
$('#modal-test').trigger('click') |
|||
assert.ok($('#modal-test').is(':visible'), 'modal not hidden') |
|||
done() |
|||
}) |
|||
.bootstrapModal('show') |
|||
}) |
|||
|
|||
QUnit.test('should close modal when escape key is pressed via keydown', function (assert) { |
|||
assert.expect(3) |
|||
var done = assert.async() |
|||
|
|||
var $div = $('<div id="modal-test"/>') |
|||
$div |
|||
.on('shown.bs.modal', function () { |
|||
assert.ok($('#modal-test').length, 'modal inserted into dom') |
|||
assert.ok($('#modal-test').is(':visible'), 'modal visible') |
|||
$div.trigger($.Event('keydown', { which: 27 })) |
|||
|
|||
setTimeout(function () { |
|||
assert.ok(!$('#modal-test').is(':visible'), 'modal hidden') |
|||
$div.remove() |
|||
done() |
|||
}, 0) |
|||
}) |
|||
.bootstrapModal('show') |
|||
}) |
|||
|
|||
QUnit.test('should not close modal when escape key is pressed via keyup', function (assert) { |
|||
assert.expect(3) |
|||
var done = assert.async() |
|||
|
|||
var $div = $('<div id="modal-test"/>') |
|||
$div |
|||
.on('shown.bs.modal', function () { |
|||
assert.ok($('#modal-test').length, 'modal inserted into dom') |
|||
assert.ok($('#modal-test').is(':visible'), 'modal visible') |
|||
$div.trigger($.Event('keyup', { which: 27 })) |
|||
|
|||
setTimeout(function () { |
|||
assert.ok($div.is(':visible'), 'modal still visible') |
|||
$div.remove() |
|||
done() |
|||
}, 0) |
|||
}) |
|||
.bootstrapModal('show') |
|||
}) |
|||
|
|||
QUnit.test('should trigger hide event once when clicking outside of modal-content', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
var triggered |
|||
|
|||
$('<div id="modal-test"><div class="contents"/></div>') |
|||
.on('shown.bs.modal', function () { |
|||
triggered = 0 |
|||
$('#modal-test').trigger('click') |
|||
}) |
|||
.on('hide.bs.modal', function () { |
|||
triggered += 1 |
|||
assert.strictEqual(triggered, 1, 'modal hide triggered once') |
|||
done() |
|||
}) |
|||
.bootstrapModal('show') |
|||
}) |
|||
|
|||
QUnit.test('should remove aria-hidden attribute when shown, add it back when hidden', function (assert) { |
|||
assert.expect(3) |
|||
var done = assert.async() |
|||
|
|||
$('<div id="modal-test" aria-hidden="true"/>') |
|||
.on('shown.bs.modal', function () { |
|||
assert.notOk($('#modal-test').is('[aria-hidden]'), 'aria-hidden attribute removed') |
|||
$(this).bootstrapModal('hide') |
|||
}) |
|||
.on('hidden.bs.modal', function () { |
|||
assert.ok($('#modal-test').is('[aria-hidden]'), 'aria-hidden attribute added') |
|||
assert.strictEqual($('#modal-test').attr('aria-hidden'), 'true', 'correct aria-hidden="true" added') |
|||
done() |
|||
}) |
|||
.bootstrapModal('show') |
|||
}) |
|||
|
|||
QUnit.test('should close reopened modal with [data-dismiss="modal"] click', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
|
|||
$('<div id="modal-test"><div class="contents"><div id="close" data-dismiss="modal"/></div></div>') |
|||
.one('shown.bs.modal', function () { |
|||
$('#close').trigger('click') |
|||
}) |
|||
.one('hidden.bs.modal', function () { |
|||
// after one open-close cycle
|
|||
assert.ok(!$('#modal-test').is(':visible'), 'modal hidden') |
|||
$(this) |
|||
.one('shown.bs.modal', function () { |
|||
$('#close').trigger('click') |
|||
}) |
|||
.one('hidden.bs.modal', function () { |
|||
assert.ok(!$('#modal-test').is(':visible'), 'modal hidden') |
|||
done() |
|||
}) |
|||
.bootstrapModal('show') |
|||
}) |
|||
.bootstrapModal('show') |
|||
}) |
|||
|
|||
QUnit.test('should restore focus to toggling element when modal is hidden after having been opened via data-api', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
var $toggleBtn = $('<button data-toggle="modal" data-target="#modal-test"/>').appendTo('#qunit-fixture') |
|||
|
|||
$('<div id="modal-test"><div class="contents"><div id="close" data-dismiss="modal"/></div></div>') |
|||
.on('hidden.bs.modal', function () { |
|||
setTimeout(function () { |
|||
assert.ok($(document.activeElement).is($toggleBtn), 'toggling element is once again focused') |
|||
done() |
|||
}, 0) |
|||
}) |
|||
.on('shown.bs.modal', function () { |
|||
$('#close').trigger('click') |
|||
}) |
|||
.appendTo('#qunit-fixture') |
|||
|
|||
$toggleBtn.trigger('click') |
|||
}) |
|||
|
|||
QUnit.test('should not restore focus to toggling element if the associated show event gets prevented', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
var $toggleBtn = $('<button data-toggle="modal" data-target="#modal-test"/>').appendTo('#qunit-fixture') |
|||
var $otherBtn = $('<button id="other-btn"/>').appendTo('#qunit-fixture') |
|||
|
|||
$('<div id="modal-test"><div class="contents"><div id="close" data-dismiss="modal"/></div>') |
|||
.one('show.bs.modal', function (e) { |
|||
e.preventDefault() |
|||
$otherBtn.trigger('focus') |
|||
setTimeout($.proxy(function () { |
|||
$(this).bootstrapModal('show') |
|||
}, this), 0) |
|||
}) |
|||
.on('hidden.bs.modal', function () { |
|||
setTimeout(function () { |
|||
assert.ok($(document.activeElement).is($otherBtn), 'focus returned to toggling element') |
|||
done() |
|||
}, 0) |
|||
}) |
|||
.on('shown.bs.modal', function () { |
|||
$('#close').trigger('click') |
|||
}) |
|||
.appendTo('#qunit-fixture') |
|||
|
|||
$toggleBtn.trigger('click') |
|||
}) |
|||
|
|||
QUnit.test('should restore inline body padding after closing', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
var originalBodyPad = 0 |
|||
var $body = $(document.body) |
|||
|
|||
$body.css('padding-right', originalBodyPad) |
|||
|
|||
$('<div id="modal-test"/>') |
|||
.on('hidden.bs.modal', function () { |
|||
var currentBodyPad = parseInt($body.css('padding-right'), 10) |
|||
assert.notStrictEqual($body.attr('style'), '', 'body has non-empty style attribute') |
|||
assert.strictEqual(currentBodyPad, originalBodyPad, 'original body padding was not changed') |
|||
$body.removeAttr('style') |
|||
done() |
|||
}) |
|||
.on('shown.bs.modal', function () { |
|||
$(this).bootstrapModal('hide') |
|||
}) |
|||
.bootstrapModal('show') |
|||
}) |
|||
|
|||
QUnit.test('should ignore values set via CSS when trying to restore body padding after closing', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
var $body = $(document.body) |
|||
var $style = $('<style>body { padding-right: 42px; }</style>').appendTo('head') |
|||
|
|||
$('<div id="modal-test"/>') |
|||
.on('hidden.bs.modal', function () { |
|||
assert.ok(!$body.attr('style'), 'body does not have inline padding set') |
|||
$style.remove() |
|||
done() |
|||
}) |
|||
.on('shown.bs.modal', function () { |
|||
$(this).bootstrapModal('hide') |
|||
}) |
|||
.bootstrapModal('show') |
|||
}) |
|||
|
|||
QUnit.test('should have a paddingRight when the modal is taller than the viewport', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
$('<div class="fixed-top fixed-bottom sticky-top is-fixed">@Johann-S</div>').appendTo('#qunit-fixture') |
|||
$('.fixed-top, .fixed-bottom, .is-fixed, .sticky-top').css('padding-right', '10px') |
|||
|
|||
$('<div id="modal-test"/>') |
|||
.on('shown.bs.modal', function () { |
|||
var paddingRight = parseInt($(document.body).css('padding-right'), 10) |
|||
assert.strictEqual(isNaN(paddingRight), false) |
|||
assert.strictEqual(paddingRight !== 0, true) |
|||
$(document.body).css('padding-right', '') // Because test case "should ignore other inline styles when trying to restore body padding after closing" fail if not
|
|||
done() |
|||
}) |
|||
.bootstrapModal('show') |
|||
}) |
|||
|
|||
QUnit.test('should remove padding-right on modal after closing', function (assert) { |
|||
assert.expect(3) |
|||
var done = assert.async() |
|||
$('<div class="fixed-top fixed-bottom is-fixed sticky-top">@Johann-S</div>').appendTo('#qunit-fixture') |
|||
$('.fixed-top, .fixed-bottom, .is-fixed, .sticky-top').css('padding-right', '10px') |
|||
|
|||
$('<div id="modal-test"/>') |
|||
.on('shown.bs.modal', function () { |
|||
var paddingRight = parseInt($(document.body).css('padding-right'), 10) |
|||
assert.strictEqual(isNaN(paddingRight), false) |
|||
assert.strictEqual(paddingRight !== 0, true) |
|||
$(this).bootstrapModal('hide') |
|||
}) |
|||
.on('hidden.bs.modal', function () { |
|||
var paddingRight = parseInt($(document.body).css('padding-right'), 10) |
|||
assert.strictEqual(paddingRight, 0) |
|||
done() |
|||
}) |
|||
.bootstrapModal('show') |
|||
}) |
|||
|
|||
QUnit.test('should ignore other inline styles when trying to restore body padding after closing', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
var $body = $(document.body) |
|||
var $style = $('<style>body { padding-right: 42px; }</style>').appendTo('head') |
|||
|
|||
$body.css('color', 'red') |
|||
|
|||
$('<div id="modal-test"/>') |
|||
.on('hidden.bs.modal', function () { |
|||
assert.strictEqual($body[0].style.paddingRight, '', 'body does not have inline padding set') |
|||
assert.strictEqual($body[0].style.color, 'red', 'body still has other inline styles set') |
|||
$body.removeAttr('style') |
|||
$style.remove() |
|||
done() |
|||
}) |
|||
.on('shown.bs.modal', function () { |
|||
$(this).bootstrapModal('hide') |
|||
}) |
|||
.bootstrapModal('show') |
|||
}) |
|||
|
|||
QUnit.test('should properly restore non-pixel inline body padding after closing', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
var $body = $(document.body) |
|||
|
|||
$body.css('padding-right', '5%') |
|||
|
|||
$('<div id="modal-test"/>') |
|||
.on('hidden.bs.modal', function () { |
|||
assert.strictEqual($body[0].style.paddingRight, '5%', 'body does not have inline padding set') |
|||
$body.removeAttr('style') |
|||
done() |
|||
}) |
|||
.on('shown.bs.modal', function () { |
|||
$(this).bootstrapModal('hide') |
|||
}) |
|||
.bootstrapModal('show') |
|||
}) |
|||
|
|||
QUnit.test('should not follow link in area tag', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
|
|||
$('<map><area id="test" shape="default" data-toggle="modal" data-target="#modal-test" href="demo.html"/></map>') |
|||
.appendTo('#qunit-fixture') |
|||
|
|||
$('<div id="modal-test"><div class="contents"><div id="close" data-dismiss="modal"/></div></div>') |
|||
.appendTo('#qunit-fixture') |
|||
|
|||
$('#test') |
|||
.on('click.bs.modal.data-api', function (event) { |
|||
assert.notOk(event.isDefaultPrevented(), 'navigating to href will happen') |
|||
|
|||
setTimeout(function () { |
|||
assert.ok(event.isDefaultPrevented(), 'model shown instead of navigating to href') |
|||
done() |
|||
}, 1) |
|||
}) |
|||
.trigger('click') |
|||
}) |
|||
}) |
@ -1,72 +0,0 @@ |
|||
/* |
|||
* grunt-contrib-qunit |
|||
* http://gruntjs.com/
|
|||
* |
|||
* Copyright (c) 2014 "Cowboy" Ben Alman, contributors |
|||
* Licensed under the MIT license. |
|||
*/ |
|||
|
|||
(function () { |
|||
'use strict' |
|||
|
|||
// Don't re-order tests.
|
|||
QUnit.config.reorder = false |
|||
// Run tests serially, not in parallel.
|
|||
QUnit.config.autorun = false |
|||
|
|||
// Send messages to the parent PhantomJS process via alert! Good times!!
|
|||
function sendMessage() { |
|||
var args = [].slice.call(arguments) |
|||
alert(JSON.stringify(args)) |
|||
} |
|||
|
|||
// These methods connect QUnit to PhantomJS.
|
|||
QUnit.log(function (obj) { |
|||
// What is this I don’t even
|
|||
if (obj.message === '[object Object], undefined:undefined') { return } |
|||
|
|||
// Parse some stuff before sending it.
|
|||
var actual |
|||
var expected |
|||
if (!obj.result) { |
|||
// Dumping large objects can be very slow, and the dump isn't used for
|
|||
// passing tests, so only dump if the test failed.
|
|||
actual = QUnit.dump.parse(obj.actual) |
|||
expected = QUnit.dump.parse(obj.expected) |
|||
} |
|||
// Send it.
|
|||
sendMessage('qunit.log', obj.result, actual, expected, obj.message, obj.source) |
|||
}) |
|||
|
|||
QUnit.testStart(function (obj) { |
|||
sendMessage('qunit.testStart', obj.name) |
|||
}) |
|||
|
|||
QUnit.testDone(function (obj) { |
|||
sendMessage('qunit.testDone', obj.name, obj.failed, obj.passed, obj.total, obj.duration) |
|||
}) |
|||
|
|||
QUnit.moduleStart(function (obj) { |
|||
sendMessage('qunit.moduleStart', obj.name) |
|||
}) |
|||
|
|||
QUnit.moduleDone(function (obj) { |
|||
if (obj.failed === 0) { |
|||
console.log('\r\u221A All tests passed in "' + obj.name + '" module') |
|||
} else { |
|||
console.log('\u00D7 ' + obj.failed + ' tests failed in "' + obj.name + '" module') |
|||
} |
|||
sendMessage('qunit.moduleDone', obj.name, obj.failed, obj.passed, obj.total) |
|||
}) |
|||
|
|||
QUnit.begin(function () { |
|||
sendMessage('qunit.begin') |
|||
console.log('\n\nStarting test suite') |
|||
console.log('================================================\n') |
|||
}) |
|||
|
|||
QUnit.done(function (obj) { |
|||
sendMessage('qunit.done', obj.failed, obj.passed, obj.total, obj.runtime) |
|||
}) |
|||
|
|||
}()) |
@ -1,367 +0,0 @@ |
|||
$(function () { |
|||
'use strict' |
|||
|
|||
QUnit.module('popover plugin') |
|||
|
|||
QUnit.test('should be defined on jquery object', function (assert) { |
|||
assert.expect(1) |
|||
assert.ok($(document.body).popover, 'popover method is defined') |
|||
}) |
|||
|
|||
QUnit.module('popover', { |
|||
beforeEach: function () { |
|||
// Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
|
|||
$.fn.bootstrapPopover = $.fn.popover.noConflict() |
|||
}, |
|||
afterEach: function () { |
|||
$.fn.popover = $.fn.bootstrapPopover |
|||
delete $.fn.bootstrapPopover |
|||
$('.popover').remove() |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should provide no conflict', function (assert) { |
|||
assert.expect(1) |
|||
assert.strictEqual($.fn.popover, undefined, 'popover was set back to undefined (org value)') |
|||
}) |
|||
|
|||
QUnit.test('should throw explicit error on undefined method', function (assert) { |
|||
assert.expect(1) |
|||
var $el = $('<div/>') |
|||
$el.bootstrapPopover() |
|||
try { |
|||
$el.bootstrapPopover('noMethod') |
|||
} |
|||
catch (err) { |
|||
assert.strictEqual(err.message, 'No method named "noMethod"') |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should return jquery collection containing the element', function (assert) { |
|||
assert.expect(2) |
|||
var $el = $('<div/>') |
|||
var $popover = $el.bootstrapPopover() |
|||
assert.ok($popover instanceof $, 'returns jquery collection') |
|||
assert.strictEqual($popover[0], $el[0], 'collection contains element') |
|||
}) |
|||
|
|||
QUnit.test('should render popover element', function (assert) { |
|||
assert.expect(2) |
|||
var $popover = $('<a href="#" title="mdo" data-content="https://twitter.com/mdo">@mdo</a>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapPopover('show') |
|||
|
|||
assert.notEqual($('.popover').length, 0, 'popover was inserted') |
|||
$popover.bootstrapPopover('hide') |
|||
assert.strictEqual($('.popover').length, 0, 'popover removed') |
|||
}) |
|||
|
|||
QUnit.test('should store popover instance in popover data object', function (assert) { |
|||
assert.expect(1) |
|||
var $popover = $('<a href="#" title="mdo" data-content="https://twitter.com/mdo">@mdo</a>').bootstrapPopover() |
|||
|
|||
assert.ok($popover.data('bs.popover'), 'popover instance exists') |
|||
}) |
|||
|
|||
QUnit.test('should store popover trigger in popover instance data object', function (assert) { |
|||
assert.expect(1) |
|||
var $popover = $('<a href="#" title="ResentedHook">@ResentedHook</a>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapPopover() |
|||
|
|||
$popover.bootstrapPopover('show') |
|||
|
|||
assert.ok($('.popover').data('bs.popover'), 'popover trigger stored in instance data') |
|||
}) |
|||
|
|||
QUnit.test('should get title and content from options', function (assert) { |
|||
assert.expect(4) |
|||
var $popover = $('<a href="#">@fat</a>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapPopover({ |
|||
title: function () { |
|||
return '@fat' |
|||
}, |
|||
content: function () { |
|||
return 'loves writing tests (╯°□°)╯︵ ┻━┻' |
|||
} |
|||
}) |
|||
|
|||
$popover.bootstrapPopover('show') |
|||
|
|||
assert.notEqual($('.popover').length, 0, 'popover was inserted') |
|||
assert.strictEqual($('.popover .popover-title').text(), '@fat', 'title correctly inserted') |
|||
assert.strictEqual($('.popover .popover-content').text(), 'loves writing tests (╯°□°)╯︵ ┻━┻', 'content correctly inserted') |
|||
|
|||
$popover.bootstrapPopover('hide') |
|||
|
|||
assert.strictEqual($('.popover').length, 0, 'popover was removed') |
|||
}) |
|||
|
|||
QUnit.test('should allow DOMElement title and content (html: true)', function (assert) { |
|||
assert.expect(5) |
|||
var title = document.createTextNode('@glebm <3 writing tests') |
|||
var content = $('<i>¯\\_(ツ)_/¯</i>').get(0) |
|||
var $popover = $('<a href="#" rel="tooltip"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapPopover({ html: true, title: title, content: content }) |
|||
|
|||
$popover.bootstrapPopover('show') |
|||
|
|||
assert.notEqual($('.popover').length, 0, 'popover inserted') |
|||
assert.strictEqual($('.popover .popover-title').text(), '@glebm <3 writing tests', 'title inserted') |
|||
assert.ok($.contains($('.popover').get(0), title), 'title node moved, not copied') |
|||
// toLowerCase because IE8 will return <I>...</I>
|
|||
assert.strictEqual($('.popover .popover-content').html().toLowerCase(), '<i>¯\\_(ツ)_/¯</i>', 'content inserted') |
|||
assert.ok($.contains($('.popover').get(0), content), 'content node moved, not copied') |
|||
}) |
|||
|
|||
QUnit.test('should allow DOMElement title and content (html: false)', function (assert) { |
|||
assert.expect(5) |
|||
var title = document.createTextNode('@glebm <3 writing tests') |
|||
var content = $('<i>¯\\_(ツ)_/¯</i>').get(0) |
|||
var $popover = $('<a href="#" rel="tooltip"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapPopover({ title: title, content: content }) |
|||
|
|||
$popover.bootstrapPopover('show') |
|||
|
|||
assert.notEqual($('.popover').length, 0, 'popover inserted') |
|||
assert.strictEqual($('.popover .popover-title').text(), '@glebm <3 writing tests', 'title inserted') |
|||
assert.ok(!$.contains($('.popover').get(0), title), 'title node copied, not moved') |
|||
assert.strictEqual($('.popover .popover-content').html(), '¯\\_(ツ)_/¯', 'content inserted') |
|||
assert.ok(!$.contains($('.popover').get(0), content), 'content node copied, not moved') |
|||
}) |
|||
|
|||
|
|||
QUnit.test('should not duplicate HTML object', function (assert) { |
|||
assert.expect(6) |
|||
var $div = $('<div/>').html('loves writing tests (╯°□°)╯︵ ┻━┻') |
|||
|
|||
var $popover = $('<a href="#">@fat</a>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapPopover({ |
|||
html: true, |
|||
content: function () { |
|||
return $div |
|||
} |
|||
}) |
|||
|
|||
$popover.bootstrapPopover('show') |
|||
assert.notEqual($('.popover').length, 0, 'popover was inserted') |
|||
assert.equal($('.popover .popover-content').html(), $div[0].outerHTML, 'content correctly inserted') |
|||
|
|||
$popover.bootstrapPopover('hide') |
|||
assert.strictEqual($('.popover').length, 0, 'popover was removed') |
|||
|
|||
$popover.bootstrapPopover('show') |
|||
assert.notEqual($('.popover').length, 0, 'popover was inserted') |
|||
assert.equal($('.popover .popover-content').html(), $div[0].outerHTML, 'content correctly inserted') |
|||
|
|||
$popover.bootstrapPopover('hide') |
|||
assert.strictEqual($('.popover').length, 0, 'popover was removed') |
|||
}) |
|||
|
|||
QUnit.test('should get title and content from attributes', function (assert) { |
|||
assert.expect(4) |
|||
var $popover = $('<a href="#" title="@mdo" data-content="loves data attributes (づ。◕‿‿◕。)づ ︵ ┻━┻" >@mdo</a>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapPopover() |
|||
.bootstrapPopover('show') |
|||
|
|||
assert.notEqual($('.popover').length, 0, 'popover was inserted') |
|||
assert.strictEqual($('.popover .popover-title').text(), '@mdo', 'title correctly inserted') |
|||
assert.strictEqual($('.popover .popover-content').text(), 'loves data attributes (づ。◕‿‿◕。)づ ︵ ┻━┻', 'content correctly inserted') |
|||
|
|||
$popover.bootstrapPopover('hide') |
|||
assert.strictEqual($('.popover').length, 0, 'popover was removed') |
|||
}) |
|||
|
|||
QUnit.test('should get title and content from attributes ignoring options passed via js', function (assert) { |
|||
assert.expect(4) |
|||
var $popover = $('<a href="#" title="@mdo" data-content="loves data attributes (づ。◕‿‿◕。)づ ︵ ┻━┻" >@mdo</a>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapPopover({ |
|||
title: 'ignored title option', |
|||
content: 'ignored content option' |
|||
}) |
|||
.bootstrapPopover('show') |
|||
|
|||
assert.notEqual($('.popover').length, 0, 'popover was inserted') |
|||
assert.strictEqual($('.popover .popover-title').text(), '@mdo', 'title correctly inserted') |
|||
assert.strictEqual($('.popover .popover-content').text(), 'loves data attributes (づ。◕‿‿◕。)づ ︵ ┻━┻', 'content correctly inserted') |
|||
|
|||
$popover.bootstrapPopover('hide') |
|||
assert.strictEqual($('.popover').length, 0, 'popover was removed') |
|||
}) |
|||
|
|||
QUnit.test('should respect custom template', function (assert) { |
|||
assert.expect(3) |
|||
var $popover = $('<a href="#">@fat</a>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapPopover({ |
|||
title: 'Test', |
|||
content: 'Test', |
|||
template: '<div class="popover foobar"><div class="arrow"></div><div class="inner"><h3 class="title"/><div class="content"><p/></div></div></div>' |
|||
}) |
|||
|
|||
$popover.bootstrapPopover('show') |
|||
|
|||
assert.notEqual($('.popover').length, 0, 'popover was inserted') |
|||
assert.ok($('.popover').hasClass('foobar'), 'custom class is present') |
|||
|
|||
$popover.bootstrapPopover('hide') |
|||
assert.strictEqual($('.popover').length, 0, 'popover was removed') |
|||
}) |
|||
|
|||
QUnit.test('should destroy popover', function (assert) { |
|||
assert.expect(7) |
|||
var $popover = $('<div/>') |
|||
.bootstrapPopover({ |
|||
trigger: 'hover' |
|||
}) |
|||
.on('click.foo', $.noop) |
|||
|
|||
assert.ok($popover.data('bs.popover'), 'popover has data') |
|||
assert.ok($._data($popover[0], 'events').mouseover && $._data($popover[0], 'events').mouseout, 'popover has hover event') |
|||
assert.strictEqual($._data($popover[0], 'events').click[0].namespace, 'foo', 'popover has extra click.foo event') |
|||
|
|||
$popover.bootstrapPopover('show') |
|||
$popover.bootstrapPopover('dispose') |
|||
|
|||
assert.ok(!$popover.hasClass('show'), 'popover is hidden') |
|||
assert.ok(!$popover.data('popover'), 'popover does not have data') |
|||
assert.strictEqual($._data($popover[0], 'events').click[0].namespace, 'foo', 'popover still has click.foo') |
|||
assert.ok(!$._data($popover[0], 'events').mouseover && !$._data($popover[0], 'events').mouseout, 'popover does not have any events') |
|||
}) |
|||
|
|||
QUnit.test('should render popover element using delegated selector', function (assert) { |
|||
assert.expect(2) |
|||
var $div = $('<div><a href="#" title="mdo" data-content="http://twitter.com/mdo">@mdo</a></div>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapPopover({ |
|||
selector: 'a', |
|||
trigger: 'click' |
|||
}) |
|||
|
|||
$div.find('a').trigger('click') |
|||
assert.notEqual($('.popover').length, 0, 'popover was inserted') |
|||
|
|||
$div.find('a').trigger('click') |
|||
assert.strictEqual($('.popover').length, 0, 'popover was removed') |
|||
}) |
|||
|
|||
QUnit.test('should detach popover content rather than removing it so that event handlers are left intact', function (assert) { |
|||
assert.expect(1) |
|||
var $content = $('<div class="content-with-handler"><a class="btn btn-warning">Button with event handler</a></div>').appendTo('#qunit-fixture') |
|||
|
|||
var handlerCalled = false |
|||
$('.content-with-handler .btn').on('click', function () { |
|||
handlerCalled = true |
|||
}) |
|||
|
|||
var $div = $('<div><a href="#">Show popover</a></div>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapPopover({ |
|||
html: true, |
|||
trigger: 'manual', |
|||
container: 'body', |
|||
content: function () { |
|||
return $content |
|||
} |
|||
}) |
|||
|
|||
var done = assert.async() |
|||
$div |
|||
.one('shown.bs.popover', function () { |
|||
$div |
|||
.one('hidden.bs.popover', function () { |
|||
$div |
|||
.one('shown.bs.popover', function () { |
|||
$('.content-with-handler .btn').trigger('click') |
|||
$div.bootstrapPopover('dispose') |
|||
assert.ok(handlerCalled, 'content\'s event handler still present') |
|||
done() |
|||
}) |
|||
.bootstrapPopover('show') |
|||
}) |
|||
.bootstrapPopover('hide') |
|||
}) |
|||
.bootstrapPopover('show') |
|||
}) |
|||
|
|||
QUnit.test('should do nothing when an attempt is made to hide an uninitialized popover', function (assert) { |
|||
assert.expect(1) |
|||
|
|||
var $popover = $('<span data-toggle="popover" data-title="some title" data-content="some content">some text</span>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('hidden.bs.popover shown.bs.popover', function () { |
|||
assert.ok(false, 'should not fire any popover events') |
|||
}) |
|||
.bootstrapPopover('hide') |
|||
assert.strictEqual($popover.data('bs.popover'), undefined, 'should not initialize the popover') |
|||
}) |
|||
|
|||
QUnit.test('should fire inserted event', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
|
|||
$('<a href="#">@Johann-S</a>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('inserted.bs.popover', function () { |
|||
assert.notEqual($('.popover').length, 0, 'popover was inserted') |
|||
assert.ok(true, 'inserted event fired') |
|||
done() |
|||
}) |
|||
.bootstrapPopover({ |
|||
title: 'Test', |
|||
content: 'Test' |
|||
}) |
|||
.bootstrapPopover('show') |
|||
}) |
|||
|
|||
QUnit.test('should throw an error when show is called on hidden elements', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
try { |
|||
$('<div data-toggle="popover" data-title="some title" data-content="@Johann-S" style="display: none"/>').bootstrapPopover('show') |
|||
} |
|||
catch (err) { |
|||
assert.strictEqual(err.message, 'Please use show on visible elements') |
|||
done() |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should hide popovers when their containing modal is closed', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
var templateHTML = '<div id="modal-test" class="modal">' + |
|||
'<div class="modal-dialog" role="document">' + |
|||
'<div class="modal-content">' + |
|||
'<div class="modal-body">' + |
|||
'<button id="popover-test" type="button" class="btn btn-secondary" data-toggle="popover" data-placement="top" data-content="Popover">' + |
|||
'Popover on top' + |
|||
'</button>' + |
|||
'</div>' + |
|||
'</div>' + |
|||
'</div>' + |
|||
'</div>' |
|||
|
|||
$(templateHTML).appendTo('#qunit-fixture') |
|||
$('#popover-test') |
|||
.on('shown.bs.popover', function () { |
|||
$('#modal-test').modal('hide') |
|||
}) |
|||
.on('hide.bs.popover', function () { |
|||
assert.ok(true, 'popover hide') |
|||
done() |
|||
}) |
|||
|
|||
$('#modal-test') |
|||
.on('shown.bs.modal', function () { |
|||
$('#popover-test').bootstrapPopover('show') |
|||
}) |
|||
.modal('show') |
|||
}) |
|||
}) |
@ -1,464 +0,0 @@ |
|||
$(function () { |
|||
'use strict' |
|||
|
|||
QUnit.module('scrollspy plugin') |
|||
|
|||
QUnit.test('should be defined on jquery object', function (assert) { |
|||
assert.expect(1) |
|||
assert.ok($(document.body).scrollspy, 'scrollspy method is defined') |
|||
}) |
|||
|
|||
QUnit.module('scrollspy', { |
|||
beforeEach: function () { |
|||
// Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
|
|||
$.fn.bootstrapScrollspy = $.fn.scrollspy.noConflict() |
|||
}, |
|||
afterEach: function () { |
|||
$.fn.scrollspy = $.fn.bootstrapScrollspy |
|||
delete $.fn.bootstrapScrollspy |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should provide no conflict', function (assert) { |
|||
assert.expect(1) |
|||
assert.strictEqual($.fn.scrollspy, undefined, 'scrollspy was set back to undefined (org value)') |
|||
}) |
|||
|
|||
QUnit.test('should throw explicit error on undefined method', function (assert) { |
|||
assert.expect(1) |
|||
var $el = $('<div/>') |
|||
$el.bootstrapScrollspy() |
|||
try { |
|||
$el.bootstrapScrollspy('noMethod') |
|||
} |
|||
catch (err) { |
|||
assert.strictEqual(err.message, 'No method named "noMethod"') |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should return jquery collection containing the element', function (assert) { |
|||
assert.expect(2) |
|||
var $el = $('<div/>') |
|||
var $scrollspy = $el.bootstrapScrollspy() |
|||
assert.ok($scrollspy instanceof $, 'returns jquery collection') |
|||
assert.strictEqual($scrollspy[0], $el[0], 'collection contains element') |
|||
}) |
|||
|
|||
QUnit.test('should only switch "active" class on current target', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
var sectionHTML = '<div id="root" class="active">' |
|||
+ '<div class="topbar">' |
|||
+ '<div class="topbar-inner">' |
|||
+ '<div class="container" id="ss-target">' |
|||
+ '<ul class="nav">' |
|||
+ '<li><a href="#masthead">Overview</a></li>' |
|||
+ '<li><a href="#detail">Detail</a></li>' |
|||
+ '</ul>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<div id="scrollspy-example" style="height: 100px; overflow: auto;">' |
|||
+ '<div style="height: 200px;">' |
|||
+ '<h4 id="masthead">Overview</h4>' |
|||
+ '<p style="height: 200px">' |
|||
+ 'Ad leggings keytar, brunch id art party dolor labore.' |
|||
+ '</p>' |
|||
+ '</div>' |
|||
+ '<div style="height: 200px;">' |
|||
+ '<h4 id="detail">Detail</h4>' |
|||
+ '<p style="height: 200px">' |
|||
+ 'Veniam marfa mustache skateboard, adipisicing fugiat velit pitchfork beard.' |
|||
+ '</p>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
var $section = $(sectionHTML).appendTo('#qunit-fixture') |
|||
|
|||
var $scrollspy = $section |
|||
.show() |
|||
.find('#scrollspy-example') |
|||
.bootstrapScrollspy({ target: '#ss-target' }) |
|||
|
|||
$scrollspy.one('scroll', function () { |
|||
assert.ok($section.hasClass('active'), '"active" class still on root node') |
|||
done() |
|||
}) |
|||
|
|||
$scrollspy.scrollTop(350) |
|||
}) |
|||
|
|||
QUnit.test('should only switch "active" class on current target specified w element', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
var sectionHTML = '<div id="root" class="active">' |
|||
+ '<div class="topbar">' |
|||
+ '<div class="topbar-inner">' |
|||
+ '<div class="container" id="ss-target">' |
|||
+ '<ul class="nav">' |
|||
+ '<li><a href="#masthead">Overview</a></li>' |
|||
+ '<li><a href="#detail">Detail</a></li>' |
|||
+ '</ul>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '<div id="scrollspy-example" style="height: 100px; overflow: auto;">' |
|||
+ '<div style="height: 200px;">' |
|||
+ '<h4 id="masthead">Overview</h4>' |
|||
+ '<p style="height: 200px">' |
|||
+ 'Ad leggings keytar, brunch id art party dolor labore.' |
|||
+ '</p>' |
|||
+ '</div>' |
|||
+ '<div style="height: 200px;">' |
|||
+ '<h4 id="detail">Detail</h4>' |
|||
+ '<p style="height: 200px">' |
|||
+ 'Veniam marfa mustache skateboard, adipisicing fugiat velit pitchfork beard.' |
|||
+ '</p>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
var $section = $(sectionHTML).appendTo('#qunit-fixture') |
|||
|
|||
var $scrollspy = $section |
|||
.show() |
|||
.find('#scrollspy-example') |
|||
.bootstrapScrollspy({ target: document.getElementById('#ss-target') }) |
|||
|
|||
$scrollspy.one('scroll', function () { |
|||
assert.ok($section.hasClass('active'), '"active" class still on root node') |
|||
done() |
|||
}) |
|||
|
|||
$scrollspy.scrollTop(350) |
|||
}) |
|||
|
|||
QUnit.test('should correctly select middle navigation option when large offset is used', function (assert) { |
|||
assert.expect(3) |
|||
var done = assert.async() |
|||
|
|||
var sectionHTML = '<div id="header" style="height: 500px;"></div>' |
|||
+ '<nav id="navigation" class="navbar">' |
|||
+ '<ul class="nav navbar-nav">' |
|||
+ '<li class="active"><a class="nav-link" id="one-link" href="#one">One</a></li>' |
|||
+ '<li><a class="nav-link" id="two-link" href="#two">Two</a></li>' |
|||
+ '<li><a class="nav-link" id="three-link" href="#three">Three</a></li>' |
|||
+ '</ul>' |
|||
+ '</nav>' |
|||
+ '<div id="content" style="height: 200px; overflow-y: auto;">' |
|||
+ '<div id="one" style="height: 500px;"></div>' |
|||
+ '<div id="two" style="height: 300px;"></div>' |
|||
+ '<div id="three" style="height: 10px;"></div>' |
|||
+ '</div>' |
|||
var $section = $(sectionHTML).appendTo('#qunit-fixture') |
|||
var $scrollspy = $section |
|||
.show() |
|||
.filter('#content') |
|||
|
|||
$scrollspy.bootstrapScrollspy({ target: '#navigation', offset: $scrollspy.position().top }) |
|||
|
|||
$scrollspy.one('scroll', function () { |
|||
assert.ok(!$section.find('#one-link').hasClass('active'), '"active" class removed from first section') |
|||
assert.ok($section.find('#two-link').hasClass('active'), '"active" class on middle section') |
|||
assert.ok(!$section.find('#three-link').hasClass('active'), '"active" class not on last section') |
|||
done() |
|||
}) |
|||
|
|||
$scrollspy.scrollTop(550) |
|||
}) |
|||
|
|||
QUnit.test('should add the active class to the correct element', function (assert) { |
|||
assert.expect(2) |
|||
var navbarHtml = |
|||
'<nav class="navbar">' |
|||
+ '<ul class="nav">' |
|||
+ '<li><a class="nav-link" id="a-1" href="#div-1">div 1</a></li>' |
|||
+ '<li><a class="nav-link" id="a-2" href="#div-2">div 2</a></li>' |
|||
+ '</ul>' |
|||
+ '</nav>' |
|||
var contentHtml = |
|||
'<div class="content" style="overflow: auto; height: 50px">' |
|||
+ '<div id="div-1" style="height: 100px; padding: 0; margin: 0">div 1</div>' |
|||
+ '<div id="div-2" style="height: 200px; padding: 0; margin: 0">div 2</div>' |
|||
+ '</div>' |
|||
|
|||
$(navbarHtml).appendTo('#qunit-fixture') |
|||
var $content = $(contentHtml) |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapScrollspy({ offset: 0, target: '.navbar' }) |
|||
|
|||
var done = assert.async() |
|||
var testElementIsActiveAfterScroll = function (element, target) { |
|||
var deferred = $.Deferred() |
|||
var scrollHeight = Math.ceil($content.scrollTop() + $(target).position().top) |
|||
$content.one('scroll', function () { |
|||
assert.ok($(element).hasClass('active'), 'target:' + target + ', element' + element) |
|||
deferred.resolve() |
|||
}) |
|||
$content.scrollTop(scrollHeight) |
|||
return deferred.promise() |
|||
} |
|||
|
|||
$.when(testElementIsActiveAfterScroll('#a-1', '#div-1')) |
|||
.then(function () { return testElementIsActiveAfterScroll('#a-2', '#div-2') }) |
|||
.then(function () { done() }) |
|||
}) |
|||
|
|||
QUnit.test('should add the active class correctly when there are nested elements at 0 scroll offset', function (assert) { |
|||
assert.expect(6) |
|||
var times = 0 |
|||
var done = assert.async() |
|||
var navbarHtml = '<nav id="navigation" class="navbar">' |
|||
+ '<ul class="nav">' |
|||
+ '<li><a id="a-1" class="nav-link" href="#div-1">div 1</a>' |
|||
+ '<ul>' |
|||
+ '<li><a id="a-2" class="nav-link" href="#div-2">div 2</a></li>' |
|||
+ '</ul>' |
|||
+ '</li>' |
|||
+ '</ul>' |
|||
+ '</nav>' |
|||
|
|||
var contentHtml = '<div class="content" style="position: absolute; top: 0px; overflow: auto; height: 50px">' |
|||
+ '<div id="div-1" style="padding: 0; margin: 0">' |
|||
+ '<div id="div-2" style="height: 200px; padding: 0; margin: 0">div 2</div>' |
|||
+ '</div>' |
|||
+ '</div>' |
|||
|
|||
$(navbarHtml).appendTo('#qunit-fixture') |
|||
|
|||
var $content = $(contentHtml) |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapScrollspy({ offset: 0, target: '#navigation' }) |
|||
|
|||
function testActiveElements() { |
|||
if (++times > 3) { return done() } |
|||
|
|||
$content.one('scroll', function () { |
|||
assert.ok($('#a-1').hasClass('active'), 'nav item for outer element has "active" class') |
|||
assert.ok($('#a-2').hasClass('active'), 'nav item for inner element has "active" class') |
|||
testActiveElements() |
|||
}) |
|||
|
|||
$content.scrollTop($content.scrollTop() + 10) |
|||
} |
|||
|
|||
testActiveElements() |
|||
}) |
|||
|
|||
QUnit.test('should clear selection if above the first section', function (assert) { |
|||
assert.expect(3) |
|||
var done = assert.async() |
|||
|
|||
var sectionHTML = '<div id="header" style="height: 500px;"></div>' |
|||
+ '<nav id="navigation" class="navbar">' |
|||
+ '<ul class="nav navbar-nav">' |
|||
+ '<li><a id="one-link" class="nav-link active" href="#one">One</a></li>' |
|||
+ '<li><a id="two-link" class="nav-link" href="#two">Two</a></li>' |
|||
+ '<li><a id="three-link" class="nav-link" href="#three">Three</a></li>' |
|||
+ '</ul>' |
|||
+ '</nav>' |
|||
$(sectionHTML).appendTo('#qunit-fixture') |
|||
|
|||
var scrollspyHTML = '<div id="content" style="height: 200px; overflow-y: auto;">' |
|||
+ '<div id="spacer" style="height: 100px;"/>' |
|||
+ '<div id="one" style="height: 100px;"/>' |
|||
+ '<div id="two" style="height: 100px;"/>' |
|||
+ '<div id="three" style="height: 100px;"/>' |
|||
+ '<div id="spacer" style="height: 100px;"/>' |
|||
+ '</div>' |
|||
var $scrollspy = $(scrollspyHTML).appendTo('#qunit-fixture') |
|||
|
|||
$scrollspy |
|||
.bootstrapScrollspy({ |
|||
target: '#navigation', |
|||
offset: $scrollspy.position().top |
|||
}) |
|||
.one('scroll', function () { |
|||
assert.strictEqual($('.active').length, 1, '"active" class on only one element present') |
|||
assert.strictEqual($('.active').is('#two-link'), true, '"active" class on second section') |
|||
$scrollspy |
|||
.one('scroll', function () { |
|||
assert.strictEqual($('.active').length, 0, 'selection cleared') |
|||
done() |
|||
}) |
|||
.scrollTop(0) |
|||
}) |
|||
.scrollTop(201) |
|||
}) |
|||
|
|||
QUnit.test('should NOT clear selection if above the first section and first section is at the top', function (assert) { |
|||
assert.expect(4) |
|||
var done = assert.async() |
|||
|
|||
var sectionHTML = '<div id="header" style="height: 500px;"></div>' |
|||
+ '<nav id="navigation" class="navbar">' |
|||
+ '<ul class="nav navbar-nav">' |
|||
+ '<li><a id="one-link" class="nav-link active" href="#one">One</a></li>' |
|||
+ '<li><a id="two-link" class="nav-link" href="#two">Two</a></li>' |
|||
+ '<li><a id="three-link" class="nav-link" href="#three">Three</a></li>' |
|||
+ '</ul>' |
|||
+ '</nav>' |
|||
$(sectionHTML).appendTo('#qunit-fixture') |
|||
|
|||
var negativeHeight = -10 |
|||
var startOfSectionTwo = 101 |
|||
|
|||
var scrollspyHTML = '<div id="content" style="height: 200px; overflow-y: auto;">' |
|||
+ '<div id="one" style="height: 100px;"/>' |
|||
+ '<div id="two" style="height: 100px;"/>' |
|||
+ '<div id="three" style="height: 100px;"/>' |
|||
+ '<div id="spacer" style="height: 100px;"/>' |
|||
+ '</div>' |
|||
var $scrollspy = $(scrollspyHTML).appendTo('#qunit-fixture') |
|||
|
|||
$scrollspy |
|||
.bootstrapScrollspy({ |
|||
target: '#navigation', |
|||
offset: $scrollspy.position().top |
|||
}) |
|||
.one('scroll', function () { |
|||
assert.strictEqual($('.active').length, 1, '"active" class on only one element present') |
|||
assert.strictEqual($('.active').is('#two-link'), true, '"active" class on second section') |
|||
$scrollspy |
|||
.one('scroll', function () { |
|||
assert.strictEqual($('.active').length, 1, '"active" class on only one element present') |
|||
assert.strictEqual($('.active').is('#one-link'), true, '"active" class on first section') |
|||
done() |
|||
}) |
|||
.scrollTop(negativeHeight) |
|||
}) |
|||
.scrollTop(startOfSectionTwo) |
|||
}) |
|||
|
|||
QUnit.test('should correctly select navigation element on backward scrolling when each target section height is 100%', function (assert) { |
|||
assert.expect(5) |
|||
var navbarHtml = |
|||
'<nav class="navbar">' |
|||
+ '<ul class="nav">' |
|||
+ '<li><a id="li-100-1" class="nav-link" href="#div-100-1">div 1</a></li>' |
|||
+ '<li><a id="li-100-2" class="nav-link" href="#div-100-2">div 2</a></li>' |
|||
+ '<li><a id="li-100-3" class="nav-link" href="#div-100-3">div 3</a></li>' |
|||
+ '<li><a id="li-100-4" class="nav-link" href="#div-100-4">div 4</a></li>' |
|||
+ '<li><a id="li-100-5" class="nav-link" href="#div-100-5">div 5</a></li>' |
|||
+ '</ul>' |
|||
+ '</nav>' |
|||
var contentHtml = |
|||
'<div class="content" style="position: relative; overflow: auto; height: 100px">' |
|||
+ '<div id="div-100-1" style="position: relative; height: 100%; padding: 0; margin: 0">div 1</div>' |
|||
+ '<div id="div-100-2" style="position: relative; height: 100%; padding: 0; margin: 0">div 2</div>' |
|||
+ '<div id="div-100-3" style="position: relative; height: 100%; padding: 0; margin: 0">div 3</div>' |
|||
+ '<div id="div-100-4" style="position: relative; height: 100%; padding: 0; margin: 0">div 4</div>' |
|||
+ '<div id="div-100-5" style="position: relative; height: 100%; padding: 0; margin: 0">div 5</div>' |
|||
+ '</div>' |
|||
|
|||
$(navbarHtml).appendTo('#qunit-fixture') |
|||
var $content = $(contentHtml) |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapScrollspy({ offset: 0, target: '.navbar' }) |
|||
|
|||
var testElementIsActiveAfterScroll = function (element, target) { |
|||
var deferred = $.Deferred() |
|||
var scrollHeight = Math.ceil($content.scrollTop() + $(target).position().top) |
|||
$content.one('scroll', function () { |
|||
assert.ok($(element).hasClass('active'), 'target:' + target + ', element: ' + element) |
|||
deferred.resolve() |
|||
}) |
|||
$content.scrollTop(scrollHeight) |
|||
return deferred.promise() |
|||
} |
|||
|
|||
var done = assert.async() |
|||
$.when(testElementIsActiveAfterScroll('#li-100-5', '#div-100-5')) |
|||
.then(function () { return testElementIsActiveAfterScroll('#li-100-4', '#div-100-4') }) |
|||
.then(function () { return testElementIsActiveAfterScroll('#li-100-3', '#div-100-3') }) |
|||
.then(function () { return testElementIsActiveAfterScroll('#li-100-2', '#div-100-2') }) |
|||
.then(function () { return testElementIsActiveAfterScroll('#li-100-1', '#div-100-1') }) |
|||
.then(function () { done() }) |
|||
}) |
|||
|
|||
QUnit.test('should allow passed in option offset method: offset', function (assert) { |
|||
assert.expect(4) |
|||
|
|||
var testOffsetMethod = function (type) { |
|||
var $navbar = $( |
|||
'<nav class="navbar"' + (type === 'data' ? ' id="navbar-offset-method-menu"' : '') + '>' |
|||
+ '<ul class="nav">' |
|||
+ '<li><a id="li-' + type + 'm-1" class="nav-link" href="#div-' + type + 'm-1">div 1</a></li>' |
|||
+ '<li><a id="li-' + type + 'm-2" class="nav-link" href="#div-' + type + 'm-2">div 2</a></li>' |
|||
+ '<li><a id="li-' + type + 'm-3" class="nav-link" href="#div-' + type + 'm-3">div 3</a></li>' |
|||
+ '</ul>' |
|||
+ '</nav>' |
|||
) |
|||
var $content = $( |
|||
'<div class="content"' + (type === 'data' ? ' data-spy="scroll" data-target="#navbar-offset-method-menu" data-offset="0" data-method="offset"' : '') + ' style="position: relative; overflow: auto; height: 100px">' |
|||
+ '<div id="div-' + type + 'm-1" style="position: relative; height: 200px; padding: 0; margin: 0">div 1</div>' |
|||
+ '<div id="div-' + type + 'm-2" style="position: relative; height: 150px; padding: 0; margin: 0">div 2</div>' |
|||
+ '<div id="div-' + type + 'm-3" style="position: relative; height: 250px; padding: 0; margin: 0">div 3</div>' |
|||
+ '</div>' |
|||
) |
|||
|
|||
$navbar.appendTo('#qunit-fixture') |
|||
$content.appendTo('#qunit-fixture') |
|||
|
|||
if (type === 'js') { |
|||
$content.bootstrapScrollspy({ target: '.navbar', offset: 0, method: 'offset' }) |
|||
} |
|||
else if (type === 'data') { |
|||
$(window).trigger('load') |
|||
} |
|||
|
|||
var $target = $('#div-' + type + 'm-2') |
|||
var scrollspy = $content.data('bs.scrollspy') |
|||
|
|||
assert.ok(scrollspy._offsets[1] === $target.offset().top, 'offset method with ' + type + ' option') |
|||
assert.ok(scrollspy._offsets[1] !== $target.position().top, 'position method with ' + type + ' option') |
|||
$navbar.remove() |
|||
$content.remove() |
|||
} |
|||
|
|||
testOffsetMethod('js') |
|||
testOffsetMethod('data') |
|||
}) |
|||
|
|||
QUnit.test('should allow passed in option offset method: position', function (assert) { |
|||
assert.expect(4) |
|||
|
|||
var testOffsetMethod = function (type) { |
|||
var $navbar = $( |
|||
'<nav class="navbar"' + (type === 'data' ? ' id="navbar-offset-method-menu"' : '') + '>' |
|||
+ '<ul class="nav">' |
|||
+ '<li><a class="nav-link" id="li-' + type + 'm-1" href="#div-' + type + 'm-1">div 1</a></li>' |
|||
+ '<li><a class="nav-link" id="li-' + type + 'm-2" href="#div-' + type + 'm-2">div 2</a></li>' |
|||
+ '<li><a class="nav-link" id="li-' + type + 'm-3" href="#div-' + type + 'm-3">div 3</a></li>' |
|||
+ '</ul>' |
|||
+ '</nav>' |
|||
) |
|||
var $content = $( |
|||
'<div class="content"' + (type === 'data' ? ' data-spy="scroll" data-target="#navbar-offset-method-menu" data-offset="0" data-method="position"' : '') + ' style="position: relative; overflow: auto; height: 100px">' |
|||
+ '<div id="div-' + type + 'm-1" style="position: relative; height: 200px; padding: 0; margin: 0">div 1</div>' |
|||
+ '<div id="div-' + type + 'm-2" style="position: relative; height: 150px; padding: 0; margin: 0">div 2</div>' |
|||
+ '<div id="div-' + type + 'm-3" style="position: relative; height: 250px; padding: 0; margin: 0">div 3</div>' |
|||
+ '</div>' |
|||
) |
|||
|
|||
$navbar.appendTo('#qunit-fixture') |
|||
$content.appendTo('#qunit-fixture') |
|||
|
|||
if (type === 'js') { $content.bootstrapScrollspy({ target: '.navbar', offset: 0, method: 'position' }) } |
|||
else if (type === 'data') { $(window).trigger('load') } |
|||
|
|||
var $target = $('#div-' + type + 'm-2') |
|||
var scrollspy = $content.data('bs.scrollspy') |
|||
|
|||
assert.ok(scrollspy._offsets[1] !== $target.offset().top, 'offset method with ' + type + ' option') |
|||
assert.ok(scrollspy._offsets[1] === $target.position().top, 'position method with ' + type + ' option') |
|||
$navbar.remove() |
|||
$content.remove() |
|||
} |
|||
|
|||
testOffsetMethod('js') |
|||
testOffsetMethod('data') |
|||
}) |
|||
|
|||
}) |
@ -1,330 +0,0 @@ |
|||
$(function () { |
|||
'use strict' |
|||
|
|||
QUnit.module('tabs plugin') |
|||
|
|||
QUnit.test('should be defined on jquery object', function (assert) { |
|||
assert.expect(1) |
|||
assert.ok($(document.body).tab, 'tabs method is defined') |
|||
}) |
|||
|
|||
QUnit.module('tabs', { |
|||
beforeEach: function () { |
|||
// Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
|
|||
$.fn.bootstrapTab = $.fn.tab.noConflict() |
|||
}, |
|||
afterEach: function () { |
|||
$.fn.tab = $.fn.bootstrapTab |
|||
delete $.fn.bootstrapTab |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should provide no conflict', function (assert) { |
|||
assert.expect(1) |
|||
assert.strictEqual($.fn.tab, undefined, 'tab was set back to undefined (org value)') |
|||
}) |
|||
|
|||
QUnit.test('should throw explicit error on undefined method', function (assert) { |
|||
assert.expect(1) |
|||
var $el = $('<div/>') |
|||
$el.bootstrapTab() |
|||
try { |
|||
$el.bootstrapTab('noMethod') |
|||
} |
|||
catch (err) { |
|||
assert.strictEqual(err.message, 'No method named "noMethod"') |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should return jquery collection containing the element', function (assert) { |
|||
assert.expect(2) |
|||
var $el = $('<div/>') |
|||
var $tab = $el.bootstrapTab() |
|||
assert.ok($tab instanceof $, 'returns jquery collection') |
|||
assert.strictEqual($tab[0], $el[0], 'collection contains element') |
|||
}) |
|||
|
|||
QUnit.test('should activate element by tab id', function (assert) { |
|||
assert.expect(2) |
|||
var tabsHTML = '<ul class="tabs">' |
|||
+ '<li><a href="#home">Home</a></li>' |
|||
+ '<li><a href="#profile">Profile</a></li>' |
|||
+ '</ul>' |
|||
|
|||
$('<ul><li id="home"/><li id="profile"/></ul>').appendTo('#qunit-fixture') |
|||
|
|||
$(tabsHTML).find('li:last a').bootstrapTab('show') |
|||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'profile') |
|||
|
|||
$(tabsHTML).find('li:first a').bootstrapTab('show') |
|||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'home') |
|||
}) |
|||
|
|||
QUnit.test('should activate element by tab id', function (assert) { |
|||
assert.expect(2) |
|||
var pillsHTML = '<ul class="pills">' |
|||
+ '<li><a href="#home">Home</a></li>' |
|||
+ '<li><a href="#profile">Profile</a></li>' |
|||
+ '</ul>' |
|||
|
|||
$('<ul><li id="home"/><li id="profile"/></ul>').appendTo('#qunit-fixture') |
|||
|
|||
$(pillsHTML).find('li:last a').bootstrapTab('show') |
|||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'profile') |
|||
|
|||
$(pillsHTML).find('li:first a').bootstrapTab('show') |
|||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'home') |
|||
}) |
|||
|
|||
QUnit.test('should activate element by tab id in ordered list', function (assert) { |
|||
assert.expect(2) |
|||
var pillsHTML = '<ol class="pills">' |
|||
+ '<li><a href="#home">Home</a></li>' |
|||
+ '<li><a href="#profile">Profile</a></li>' |
|||
+ '</ol>' |
|||
|
|||
$('<ol><li id="home"/><li id="profile"/></ol>').appendTo('#qunit-fixture') |
|||
|
|||
$(pillsHTML).find('li:last a').bootstrapTab('show') |
|||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'profile') |
|||
|
|||
$(pillsHTML).find('li:first a').bootstrapTab('show') |
|||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'home') |
|||
}) |
|||
|
|||
QUnit.test('should activate element by tab id in nav list', function (assert) { |
|||
assert.expect(2) |
|||
var tabsHTML = '<nav class="nav">' + |
|||
'<a href="#home">Home</a>' + |
|||
'<a href="#profile">Profile</a>' + |
|||
'</nav>' |
|||
|
|||
$('<nav><div id="home"></div><div id="profile"></div></nav>').appendTo('#qunit-fixture') |
|||
|
|||
$(tabsHTML).find('a:last').bootstrapTab('show') |
|||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'profile') |
|||
|
|||
$(tabsHTML).find('a:first').bootstrapTab('show') |
|||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'home') |
|||
}) |
|||
|
|||
QUnit.test('should not fire shown when show is prevented', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
$('<div class="tab"/>') |
|||
.on('show.bs.tab', function (e) { |
|||
e.preventDefault() |
|||
assert.ok(true, 'show event fired') |
|||
done() |
|||
}) |
|||
.on('shown.bs.tab', function () { |
|||
assert.ok(false, 'shown event fired') |
|||
}) |
|||
.bootstrapTab('show') |
|||
}) |
|||
|
|||
QUnit.test('should not fire shown when tab is already active', function (assert) { |
|||
assert.expect(0) |
|||
var tabsHTML = '<ul class="nav nav-tabs" role="tablist">' |
|||
+ '<li class="nav-item"><a href="#home" class="nav-link active" role="tab">Home</a></li>' |
|||
+ '<li class="nav-item"><a href="#profile" class="nav-link" role="tab">Profile</a></li>' |
|||
+ '</ul>' |
|||
+ '<div class="tab-content">' |
|||
+ '<div class="tab-pane active" id="home" role="tabpanel"></div>' |
|||
+ '<div class="tab-pane" id="profile" role="tabpanel"></div>' |
|||
+ '</div>' |
|||
|
|||
$(tabsHTML) |
|||
.find('a.active') |
|||
.on('shown.bs.tab', function () { |
|||
assert.ok(true, 'shown event fired') |
|||
}) |
|||
.bootstrapTab('show') |
|||
}) |
|||
|
|||
QUnit.test('should not fire shown when tab is disabled', function (assert) { |
|||
assert.expect(0) |
|||
var tabsHTML = '<ul class="nav nav-tabs" role="tablist">' |
|||
+ '<li class="nav-item"><a href="#home" class="nav-link active" role="tab">Home</a></li>' |
|||
+ '<li class="nav-item"><a href="#profile" class="nav-link disabled" role="tab">Profile</a></li>' |
|||
+ '</ul>' |
|||
+ '<div class="tab-content">' |
|||
+ '<div class="tab-pane active" id="home" role="tabpanel"></div>' |
|||
+ '<div class="tab-pane" id="profile" role="tabpanel"></div>' |
|||
+ '</div>' |
|||
|
|||
$(tabsHTML) |
|||
.find('a.disabled') |
|||
.on('shown.bs.tab', function () { |
|||
assert.ok(true, 'shown event fired') |
|||
}) |
|||
.bootstrapTab('show') |
|||
}) |
|||
|
|||
QUnit.test('show and shown events should reference correct relatedTarget', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
|
|||
var dropHTML = '<ul class="drop">' |
|||
+ '<li class="dropdown"><a data-toggle="dropdown" href="#">1</a>' |
|||
+ '<ul class="dropdown-menu">' |
|||
+ '<li><a href="#1-1" data-toggle="tab">1-1</a></li>' |
|||
+ '<li><a href="#1-2" data-toggle="tab">1-2</a></li>' |
|||
+ '</ul>' |
|||
+ '</li>' |
|||
+ '</ul>' |
|||
|
|||
$(dropHTML) |
|||
.find('ul > li:first a') |
|||
.bootstrapTab('show') |
|||
.end() |
|||
.find('ul > li:last a') |
|||
.on('show.bs.tab', function (e) { |
|||
assert.strictEqual(e.relatedTarget.hash, '#1-1', 'references correct element as relatedTarget') |
|||
}) |
|||
.on('shown.bs.tab', function (e) { |
|||
assert.strictEqual(e.relatedTarget.hash, '#1-1', 'references correct element as relatedTarget') |
|||
done() |
|||
}) |
|||
.bootstrapTab('show') |
|||
}) |
|||
|
|||
QUnit.test('should fire hide and hidden events', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
|
|||
var tabsHTML = '<ul class="tabs">' |
|||
+ '<li><a href="#home">Home</a></li>' |
|||
+ '<li><a href="#profile">Profile</a></li>' |
|||
+ '</ul>' |
|||
|
|||
$(tabsHTML) |
|||
.find('li:first a') |
|||
.on('hide.bs.tab', function () { |
|||
assert.ok(true, 'hide event fired') |
|||
}) |
|||
.bootstrapTab('show') |
|||
.end() |
|||
.find('li:last a') |
|||
.bootstrapTab('show') |
|||
|
|||
$(tabsHTML) |
|||
.find('li:first a') |
|||
.on('hidden.bs.tab', function () { |
|||
assert.ok(true, 'hidden event fired') |
|||
done() |
|||
}) |
|||
.bootstrapTab('show') |
|||
.end() |
|||
.find('li:last a') |
|||
.bootstrapTab('show') |
|||
}) |
|||
|
|||
QUnit.test('should not fire hidden when hide is prevented', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
var tabsHTML = '<ul class="tabs">' |
|||
+ '<li><a href="#home">Home</a></li>' |
|||
+ '<li><a href="#profile">Profile</a></li>' |
|||
+ '</ul>' |
|||
|
|||
$(tabsHTML) |
|||
.find('li:first a') |
|||
.on('hide.bs.tab', function (e) { |
|||
e.preventDefault() |
|||
assert.ok(true, 'hide event fired') |
|||
done() |
|||
}) |
|||
.on('hidden.bs.tab', function () { |
|||
assert.ok(false, 'hidden event fired') |
|||
}) |
|||
.bootstrapTab('show') |
|||
.end() |
|||
.find('li:last a') |
|||
.bootstrapTab('show') |
|||
}) |
|||
|
|||
QUnit.test('hide and hidden events contain correct relatedTarget', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
|
|||
var tabsHTML = '<ul class="tabs">' |
|||
+ '<li><a href="#home">Home</a></li>' |
|||
+ '<li><a href="#profile">Profile</a></li>' |
|||
+ '</ul>' |
|||
|
|||
$(tabsHTML) |
|||
.find('li:first a') |
|||
.on('hide.bs.tab', function (e) { |
|||
assert.strictEqual(e.relatedTarget.hash, '#profile', 'references correct element as relatedTarget') |
|||
}) |
|||
.on('hidden.bs.tab', function (e) { |
|||
assert.strictEqual(e.relatedTarget.hash, '#profile', 'references correct element as relatedTarget') |
|||
done() |
|||
}) |
|||
.bootstrapTab('show') |
|||
.end() |
|||
.find('li:last a') |
|||
.bootstrapTab('show') |
|||
}) |
|||
|
|||
QUnit.test('selected tab should have aria-expanded', function (assert) { |
|||
assert.expect(8) |
|||
var tabsHTML = '<ul class="nav nav-tabs">' |
|||
+ '<li><a class="nav-item active" href="#home" toggle="tab" aria-expanded="true">Home</a></li>' |
|||
+ '<li><a class="nav-item" href="#profile" toggle="tab" aria-expanded="false">Profile</a></li>' |
|||
+ '</ul>' |
|||
var $tabs = $(tabsHTML).appendTo('#qunit-fixture') |
|||
|
|||
$tabs.find('li:first a').bootstrapTab('show') |
|||
assert.strictEqual($tabs.find('.active').attr('aria-expanded'), 'true', 'shown tab has aria-expanded = true') |
|||
assert.strictEqual($tabs.find('a:not(.active)').attr('aria-expanded'), 'false', 'hidden tab has aria-expanded = false') |
|||
|
|||
$tabs.find('li:last a').trigger('click') |
|||
assert.strictEqual($tabs.find('.active').attr('aria-expanded'), 'true', 'after click, shown tab has aria-expanded = true') |
|||
assert.strictEqual($tabs.find('a:not(.active)').attr('aria-expanded'), 'false', 'after click, hidden tab has aria-expanded = false') |
|||
|
|||
$tabs.find('li:first a').bootstrapTab('show') |
|||
assert.strictEqual($tabs.find('.active').attr('aria-expanded'), 'true', 'shown tab has aria-expanded = true') |
|||
assert.strictEqual($tabs.find('a:not(.active)').attr('aria-expanded'), 'false', 'hidden tab has aria-expanded = false') |
|||
|
|||
$tabs.find('li:first a').trigger('click') |
|||
assert.strictEqual($tabs.find('.active').attr('aria-expanded'), 'true', 'after second show event, shown tab still has aria-expanded = true') |
|||
assert.strictEqual($tabs.find('a:not(.active)').attr('aria-expanded'), 'false', 'after second show event, hidden tab has aria-expanded = false') |
|||
}) |
|||
|
|||
QUnit.test('selected tab should deactivate previous selected tab', function (assert) { |
|||
assert.expect(2) |
|||
var tabsHTML = '<ul class="nav nav-tabs">' |
|||
+ '<li class="nav-item"><a class="nav-link active" href="#home" data-toggle="tab">Home</a></li>' |
|||
+ '<li class="nav-item"><a class="nav-link" href="#profile" data-toggle="tab">Profile</a></li>' |
|||
+ '</ul>' |
|||
var $tabs = $(tabsHTML).appendTo('#qunit-fixture') |
|||
|
|||
$tabs.find('li:last a').trigger('click') |
|||
assert.notOk($tabs.find('li:first a').hasClass('active')) |
|||
assert.ok($tabs.find('li:last a').hasClass('active')) |
|||
}) |
|||
|
|||
QUnit.test('selected tab should deactivate previous selected link in dropdown', function (assert) { |
|||
assert.expect(3) |
|||
var tabsHTML = '<ul class="nav nav-tabs">' |
|||
+ '<li class="nav-item"><a class="nav-link" href="#home" data-toggle="tab">Home</a></li>' |
|||
+ '<li class="nav-item"><a class="nav-link" href="#profile" data-toggle="tab">Profile</a></li>' |
|||
+ '<li class="nav-item dropdown"><a class="nav-link dropdown-toggle active" data-toggle="dropdown" href="#">Dropdown</a>' |
|||
+ '<div class="dropdown-menu">' |
|||
+ '<a class="dropdown-item active" href="#dropdown1" id="dropdown1-tab" data-toggle="tab">@fat</a>' |
|||
+ '<a class="dropdown-item" href="#dropdown2" id="dropdown2-tab" data-toggle="tab">@mdo</a>' |
|||
+ '</div>' |
|||
+ '</li>' |
|||
+ '</ul>' |
|||
var $tabs = $(tabsHTML).appendTo('#qunit-fixture') |
|||
|
|||
$tabs.find('li:first > a').trigger('click') |
|||
assert.ok($tabs.find('li:first a').hasClass('active')) |
|||
assert.notOk($tabs.find('li:last > a').hasClass('active')) |
|||
assert.notOk($tabs.find('li:last > .dropdown-menu > a:first').hasClass('active')) |
|||
}) |
|||
}) |
@ -1,872 +0,0 @@ |
|||
$(function () { |
|||
'use strict' |
|||
|
|||
QUnit.module('tooltip plugin') |
|||
|
|||
QUnit.test('should be defined on jquery object', function (assert) { |
|||
assert.expect(1) |
|||
assert.ok($(document.body).tooltip, 'tooltip method is defined') |
|||
}) |
|||
|
|||
QUnit.module('tooltip', { |
|||
beforeEach: function () { |
|||
// Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
|
|||
$.fn.bootstrapTooltip = $.fn.tooltip.noConflict() |
|||
}, |
|||
afterEach: function () { |
|||
$.fn.tooltip = $.fn.bootstrapTooltip |
|||
delete $.fn.bootstrapTooltip |
|||
$('.tooltip').remove() |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should provide no conflict', function (assert) { |
|||
assert.expect(1) |
|||
assert.strictEqual($.fn.tooltip, undefined, 'tooltip was set back to undefined (org value)') |
|||
}) |
|||
|
|||
QUnit.test('should throw explicit error on undefined method', function (assert) { |
|||
assert.expect(1) |
|||
var $el = $('<div/>') |
|||
$el.bootstrapTooltip() |
|||
try { |
|||
$el.bootstrapTooltip('noMethod') |
|||
} |
|||
catch (err) { |
|||
assert.strictEqual(err.message, 'No method named "noMethod"') |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should return jquery collection containing the element', function (assert) { |
|||
assert.expect(2) |
|||
var $el = $('<div/>') |
|||
var $tooltip = $el.bootstrapTooltip() |
|||
assert.ok($tooltip instanceof $, 'returns jquery collection') |
|||
assert.strictEqual($tooltip[0], $el[0], 'collection contains element') |
|||
}) |
|||
|
|||
QUnit.test('should expose default settings', function (assert) { |
|||
assert.expect(1) |
|||
assert.ok($.fn.bootstrapTooltip.Constructor.Default, 'defaults is defined') |
|||
}) |
|||
|
|||
QUnit.test('should empty title attribute', function (assert) { |
|||
assert.expect(1) |
|||
var $trigger = $('<a href="#" rel="tooltip" title="Another tooltip"/>').bootstrapTooltip() |
|||
assert.strictEqual($trigger.attr('title'), '', 'title attribute was emptied') |
|||
}) |
|||
|
|||
QUnit.test('should add data attribute for referencing original title', function (assert) { |
|||
assert.expect(1) |
|||
var $trigger = $('<a href="#" rel="tooltip" title="Another tooltip"/>').bootstrapTooltip() |
|||
assert.strictEqual($trigger.attr('data-original-title'), 'Another tooltip', 'original title preserved in data attribute') |
|||
}) |
|||
|
|||
QUnit.test('should add aria-describedby to the trigger on show', function (assert) { |
|||
assert.expect(3) |
|||
var $trigger = $('<a href="#" rel="tooltip" title="Another tooltip"/>') |
|||
.bootstrapTooltip() |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip('show') |
|||
|
|||
var id = $('.tooltip').attr('id') |
|||
|
|||
assert.strictEqual($('#' + id).length, 1, 'has a unique id') |
|||
assert.strictEqual($('.tooltip').attr('aria-describedby'), $trigger.attr('id'), 'tooltip id and aria-describedby on trigger match') |
|||
assert.ok($trigger[0].hasAttribute('aria-describedby'), 'trigger has aria-describedby') |
|||
}) |
|||
|
|||
QUnit.test('should remove aria-describedby from trigger on hide', function (assert) { |
|||
assert.expect(2) |
|||
var $trigger = $('<a href="#" rel="tooltip" title="Another tooltip"/>') |
|||
.bootstrapTooltip() |
|||
.appendTo('#qunit-fixture') |
|||
|
|||
$trigger.bootstrapTooltip('show') |
|||
assert.ok($trigger[0].hasAttribute('aria-describedby'), 'trigger has aria-describedby') |
|||
|
|||
$trigger.bootstrapTooltip('hide') |
|||
assert.ok(!$trigger[0].hasAttribute('aria-describedby'), 'trigger does not have aria-describedby') |
|||
}) |
|||
|
|||
QUnit.test('should assign a unique id tooltip element', function (assert) { |
|||
assert.expect(2) |
|||
$('<a href="#" rel="tooltip" title="Another tooltip"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip('show') |
|||
|
|||
var id = $('.tooltip').attr('id') |
|||
|
|||
assert.strictEqual($('#' + id).length, 1, 'tooltip has unique id') |
|||
assert.strictEqual(id.indexOf('tooltip'), 0, 'tooltip id has prefix') |
|||
}) |
|||
|
|||
QUnit.test('should place tooltips relative to placement option', function (assert) { |
|||
assert.expect(2) |
|||
var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip({ placement: 'bottom' }) |
|||
|
|||
$tooltip.bootstrapTooltip('show') |
|||
|
|||
assert |
|||
.ok($('.tooltip') |
|||
.is('.fade.bs-tether-element-attached-top.bs-tether-element-attached-center.show'), 'has correct classes applied') |
|||
|
|||
$tooltip.bootstrapTooltip('hide') |
|||
|
|||
assert.strictEqual($tooltip.data('bs.tooltip').tip.parentNode, null, 'tooltip removed') |
|||
}) |
|||
|
|||
QUnit.test('should allow html entities', function (assert) { |
|||
assert.expect(2) |
|||
var $tooltip = $('<a href="#" rel="tooltip" title="<b>@fat</b>"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip({ html: true }) |
|||
|
|||
$tooltip.bootstrapTooltip('show') |
|||
assert.notEqual($('.tooltip b').length, 0, 'b tag was inserted') |
|||
|
|||
$tooltip.bootstrapTooltip('hide') |
|||
assert.strictEqual($tooltip.data('bs.tooltip').tip.parentNode, null, 'tooltip removed') |
|||
}) |
|||
|
|||
QUnit.test('should allow DOMElement title (html: false)', function (assert) { |
|||
assert.expect(3) |
|||
var title = document.createTextNode('<3 writing tests') |
|||
var $tooltip = $('<a href="#" rel="tooltip"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip({ title: title }) |
|||
|
|||
$tooltip.bootstrapTooltip('show') |
|||
|
|||
assert.notEqual($('.tooltip').length, 0, 'tooltip inserted') |
|||
assert.strictEqual($('.tooltip').text(), '<3 writing tests', 'title inserted') |
|||
assert.ok(!$.contains($('.tooltip').get(0), title), 'title node copied, not moved') |
|||
}) |
|||
|
|||
QUnit.test('should allow DOMElement title (html: true)', function (assert) { |
|||
assert.expect(3) |
|||
var title = document.createTextNode('<3 writing tests') |
|||
var $tooltip = $('<a href="#" rel="tooltip"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip({ html: true, title: title }) |
|||
|
|||
$tooltip.bootstrapTooltip('show') |
|||
|
|||
assert.notEqual($('.tooltip').length, 0, 'tooltip inserted') |
|||
assert.strictEqual($('.tooltip').text(), '<3 writing tests', 'title inserted') |
|||
assert.ok($.contains($('.tooltip').get(0), title), 'title node moved, not copied') |
|||
}) |
|||
|
|||
|
|||
QUnit.test('should respect custom classes', function (assert) { |
|||
assert.expect(2) |
|||
var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip({ template: '<div class="tooltip some-class"><div class="tooltip-arrow"/><div class="tooltip-inner"/></div>' }) |
|||
|
|||
$tooltip.bootstrapTooltip('show') |
|||
assert.ok($('.tooltip').hasClass('some-class'), 'custom class is present') |
|||
|
|||
$tooltip.bootstrapTooltip('hide') |
|||
assert.strictEqual($tooltip.data('bs.tooltip').tip.parentNode, null, 'tooltip removed') |
|||
}) |
|||
|
|||
QUnit.test('should fire show event', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
$('<div title="tooltip title"/>') |
|||
.on('show.bs.tooltip', function () { |
|||
assert.ok(true, 'show event fired') |
|||
done() |
|||
}) |
|||
.bootstrapTooltip('show') |
|||
}) |
|||
|
|||
QUnit.test('should throw an error when show is called on hidden elements', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
try { |
|||
$('<div title="tooltip title" style="display: none"/>').bootstrapTooltip('show') |
|||
} |
|||
catch (err) { |
|||
assert.strictEqual(err.message, 'Please use show on visible elements') |
|||
done() |
|||
} |
|||
}) |
|||
|
|||
QUnit.test('should fire inserted event', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
|
|||
$('<div title="tooltip title"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('inserted.bs.tooltip', function () { |
|||
assert.notEqual($('.tooltip').length, 0, 'tooltip was inserted') |
|||
assert.ok(true, 'inserted event fired') |
|||
done() |
|||
}) |
|||
.bootstrapTooltip('show') |
|||
}) |
|||
|
|||
QUnit.test('should fire shown event', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
$('<div title="tooltip title"></div>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('shown.bs.tooltip', function () { |
|||
assert.ok(true, 'shown was called') |
|||
done() |
|||
}) |
|||
.bootstrapTooltip('show') |
|||
}) |
|||
|
|||
QUnit.test('should not fire shown event when show was prevented', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
$('<div title="tooltip title"/>') |
|||
.on('show.bs.tooltip', function (e) { |
|||
e.preventDefault() |
|||
assert.ok(true, 'show event fired') |
|||
done() |
|||
}) |
|||
.on('shown.bs.tooltip', function () { |
|||
assert.ok(false, 'shown event fired') |
|||
}) |
|||
.bootstrapTooltip('show') |
|||
}) |
|||
|
|||
QUnit.test('should fire hide event', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
$('<div title="tooltip title"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('shown.bs.tooltip', function () { |
|||
$(this).bootstrapTooltip('hide') |
|||
}) |
|||
.on('hide.bs.tooltip', function () { |
|||
assert.ok(true, 'hide event fired') |
|||
done() |
|||
}) |
|||
.bootstrapTooltip('show') |
|||
}) |
|||
|
|||
QUnit.test('should fire hidden event', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
$('<div title="tooltip title"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('shown.bs.tooltip', function () { |
|||
$(this).bootstrapTooltip('hide') |
|||
}) |
|||
.on('hidden.bs.tooltip', function () { |
|||
assert.ok(true, 'hidden event fired') |
|||
done() |
|||
}) |
|||
.bootstrapTooltip('show') |
|||
}) |
|||
|
|||
QUnit.test('should not fire hidden event when hide was prevented', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
$('<div title="tooltip title"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('shown.bs.tooltip', function () { |
|||
$(this).bootstrapTooltip('hide') |
|||
}) |
|||
.on('hide.bs.tooltip', function (e) { |
|||
e.preventDefault() |
|||
assert.ok(true, 'hide event fired') |
|||
done() |
|||
}) |
|||
.on('hidden.bs.tooltip', function () { |
|||
assert.ok(false, 'hidden event fired') |
|||
}) |
|||
.bootstrapTooltip('show') |
|||
}) |
|||
|
|||
QUnit.test('should destroy tooltip', function (assert) { |
|||
assert.expect(7) |
|||
var $tooltip = $('<div/>') |
|||
.bootstrapTooltip() |
|||
.on('click.foo', function () {}) |
|||
|
|||
assert.ok($tooltip.data('bs.tooltip'), 'tooltip has data') |
|||
assert.ok($._data($tooltip[0], 'events').mouseover && $._data($tooltip[0], 'events').mouseout, 'tooltip has hover events') |
|||
assert.strictEqual($._data($tooltip[0], 'events').click[0].namespace, 'foo', 'tooltip has extra click.foo event') |
|||
|
|||
$tooltip.bootstrapTooltip('show') |
|||
$tooltip.bootstrapTooltip('dispose') |
|||
|
|||
assert.ok(!$tooltip.hasClass('show'), 'tooltip is hidden') |
|||
assert.ok(!$._data($tooltip[0], 'bs.tooltip'), 'tooltip does not have data') |
|||
assert.strictEqual($._data($tooltip[0], 'events').click[0].namespace, 'foo', 'tooltip still has click.foo') |
|||
assert.ok(!$._data($tooltip[0], 'events').mouseover && !$._data($tooltip[0], 'events').mouseout, 'tooltip does not have hover events') |
|||
}) |
|||
|
|||
// QUnit.test('should show tooltip with delegate selector on click', function (assert) {
|
|||
// assert.expect(2)
|
|||
// var $div = $('<div><a href="#" rel="tooltip" title="Another tooltip"/></div>')
|
|||
// .appendTo('#qunit-fixture')
|
|||
// .bootstrapTooltip({
|
|||
// selector: 'a[rel="tooltip"]',
|
|||
// trigger: 'click'
|
|||
// })
|
|||
|
|||
// $div.find('a').trigger('click')
|
|||
// assert.ok($('.tooltip').is('.fade.in'), 'tooltip is faded in')
|
|||
|
|||
// $div.find('a').trigger('click')
|
|||
// assert.strictEqual($div.data('bs.tooltip').tip.parentNode, null, 'tooltip removed')
|
|||
// })
|
|||
|
|||
QUnit.test('should show tooltip when toggle is called', function (assert) { |
|||
assert.expect(1) |
|||
$('<a href="#" rel="tooltip" title="tooltip on toggle"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip({ trigger: 'manual' }) |
|||
.bootstrapTooltip('toggle') |
|||
|
|||
assert.ok($('.tooltip').is('.fade.show'), 'tooltip is faded active') |
|||
}) |
|||
|
|||
QUnit.test('should hide previously shown tooltip when toggle is called on tooltip', function (assert) { |
|||
assert.expect(1) |
|||
$('<a href="#" rel="tooltip" title="tooltip on toggle">@ResentedHook</a>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip({ trigger: 'manual' }) |
|||
.bootstrapTooltip('show') |
|||
|
|||
$('.tooltip').bootstrapTooltip('toggle') |
|||
assert.ok($('.tooltip').not('.fade.show'), 'tooltip was faded out') |
|||
}) |
|||
|
|||
QUnit.test('should place tooltips inside body when container is body', function (assert) { |
|||
assert.expect(3) |
|||
var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip({ container: 'body' }) |
|||
.bootstrapTooltip('show') |
|||
|
|||
assert.notEqual($('body > .tooltip').length, 0, 'tooltip is direct descendant of body') |
|||
assert.strictEqual($('#qunit-fixture > .tooltip').length, 0, 'tooltip is not in parent') |
|||
|
|||
$tooltip.bootstrapTooltip('hide') |
|||
assert.strictEqual($('body > .tooltip').length, 0, 'tooltip was removed from dom') |
|||
}) |
|||
|
|||
QUnit.test('should add position class before positioning so that position-specific styles are taken into account', function (assert) { |
|||
assert.expect(1) |
|||
var styles = '<style>' |
|||
+ '.tooltip.right { white-space: nowrap; }' |
|||
+ '.tooltip.right .tooltip-inner { max-width: none; }' |
|||
+ '</style>' |
|||
var $styles = $(styles).appendTo('head') |
|||
|
|||
var $container = $('<div/>').appendTo('#qunit-fixture') |
|||
var $target = $('<a href="#" rel="tooltip" title="very very very very very very very very long tooltip in one line"/>') |
|||
.appendTo($container) |
|||
.bootstrapTooltip({ |
|||
placement: 'right' |
|||
}) |
|||
.bootstrapTooltip('show') |
|||
|
|||
var $tooltip = $($target.data('bs.tooltip').tip) |
|||
|
|||
// this is some dumb hack stuff because sub pixels in firefox
|
|||
var top = Math.round($target.offset().top + $target[0].offsetHeight / 2 - $tooltip[0].offsetHeight / 2) |
|||
var top2 = Math.round($tooltip.offset().top) |
|||
var topDiff = top - top2 |
|||
assert.ok(topDiff <= 1 && topDiff >= -1) |
|||
$target.bootstrapTooltip('hide') |
|||
|
|||
$container.remove() |
|||
$styles.remove() |
|||
}) |
|||
|
|||
QUnit.test('should use title attribute for tooltip text', function (assert) { |
|||
assert.expect(2) |
|||
var $tooltip = $('<a href="#" rel="tooltip" title="Simple tooltip"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip() |
|||
|
|||
$tooltip.bootstrapTooltip('show') |
|||
assert.strictEqual($('.tooltip').children('.tooltip-inner').text(), 'Simple tooltip', 'title from title attribute is set') |
|||
|
|||
$tooltip.bootstrapTooltip('hide') |
|||
assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom') |
|||
}) |
|||
|
|||
QUnit.test('should prefer title attribute over title option', function (assert) { |
|||
assert.expect(2) |
|||
var $tooltip = $('<a href="#" rel="tooltip" title="Simple tooltip"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip({ |
|||
title: 'This is a tooltip with some content' |
|||
}) |
|||
|
|||
$tooltip.bootstrapTooltip('show') |
|||
assert.strictEqual($('.tooltip').children('.tooltip-inner').text(), 'Simple tooltip', 'title is set from title attribute while preferred over title option') |
|||
|
|||
$tooltip.bootstrapTooltip('hide') |
|||
assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom') |
|||
}) |
|||
|
|||
QUnit.test('should use title option', function (assert) { |
|||
assert.expect(2) |
|||
var $tooltip = $('<a href="#" rel="tooltip"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip({ |
|||
title: 'This is a tooltip with some content' |
|||
}) |
|||
|
|||
$tooltip.bootstrapTooltip('show') |
|||
assert.strictEqual($('.tooltip').children('.tooltip-inner').text(), 'This is a tooltip with some content', 'title from title option is set') |
|||
|
|||
$tooltip.bootstrapTooltip('hide') |
|||
assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom') |
|||
}) |
|||
|
|||
QUnit.test('should not error when trying to show an top-placed tooltip that has been removed from the dom', function (assert) { |
|||
assert.expect(1) |
|||
var passed = true |
|||
var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.one('show.bs.tooltip', function () { |
|||
$(this).remove() |
|||
}) |
|||
.bootstrapTooltip({ placement: 'top' }) |
|||
|
|||
try { |
|||
$tooltip.bootstrapTooltip('show') |
|||
} catch (err) { |
|||
passed = false |
|||
console.log(err) |
|||
} |
|||
|
|||
assert.ok(passed, '.tooltip(\'show\') should not throw an error if element no longer is in dom') |
|||
}) |
|||
|
|||
QUnit.test('should place tooltip on top of element', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
|
|||
var containerHTML = '<div>' |
|||
+ '<p style="margin-top: 200px">' |
|||
+ '<a href="#" title="very very very very very very very long tooltip">Hover me</a>' |
|||
+ '</p>' |
|||
+ '</div>' |
|||
|
|||
var $container = $(containerHTML) |
|||
.css({ |
|||
position: 'absolute', |
|||
bottom: 0, |
|||
left: 0, |
|||
textAlign: 'right', |
|||
width: 300, |
|||
height: 300 |
|||
}) |
|||
.appendTo('#qunit-fixture') |
|||
|
|||
var $trigger = $container |
|||
.find('a') |
|||
.css('margin-top', 200) |
|||
.bootstrapTooltip({ |
|||
placement: 'top', |
|||
animate: false |
|||
}) |
|||
.bootstrapTooltip('show') |
|||
|
|||
var $tooltip = $($trigger.data('bs.tooltip').tip) |
|||
|
|||
setTimeout(function () { |
|||
assert.ok(Math.round($tooltip.offset().top + $tooltip.outerHeight()) <= Math.round($trigger.offset().top)) |
|||
done() |
|||
}, 0) |
|||
}) |
|||
|
|||
QUnit.test('should show tooltip if leave event hasn\'t occurred before delay expires', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
|
|||
var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip({ delay: 150 }) |
|||
|
|||
setTimeout(function () { |
|||
assert.ok(!$('.tooltip').is('.fade.show'), '100ms: tooltip is not faded active') |
|||
}, 100) |
|||
|
|||
setTimeout(function () { |
|||
assert.ok($('.tooltip').is('.fade.show'), '200ms: tooltip is faded active') |
|||
done() |
|||
}, 200) |
|||
|
|||
$tooltip.trigger('mouseenter') |
|||
}) |
|||
|
|||
QUnit.test('should not show tooltip if leave event occurs before delay expires', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
|
|||
var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip({ delay: 150 }) |
|||
|
|||
setTimeout(function () { |
|||
assert.ok(!$('.tooltip').is('.fade.show'), '100ms: tooltip not faded active') |
|||
$tooltip.trigger('mouseout') |
|||
}, 100) |
|||
|
|||
setTimeout(function () { |
|||
assert.ok(!$('.tooltip').is('.fade.show'), '200ms: tooltip not faded active') |
|||
done() |
|||
}, 200) |
|||
|
|||
$tooltip.trigger('mouseenter') |
|||
}) |
|||
|
|||
QUnit.test('should not hide tooltip if leave event occurs and enter event occurs within the hide delay', function (assert) { |
|||
assert.expect(3) |
|||
var done = assert.async() |
|||
|
|||
var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip({ delay: { show: 0, hide: 150 } }) |
|||
|
|||
setTimeout(function () { |
|||
assert.ok($('.tooltip').is('.fade.show'), '1ms: tooltip faded active') |
|||
$tooltip.trigger('mouseout') |
|||
|
|||
setTimeout(function () { |
|||
assert.ok($('.tooltip').is('.fade.show'), '100ms: tooltip still faded active') |
|||
$tooltip.trigger('mouseenter') |
|||
}, 100) |
|||
|
|||
setTimeout(function () { |
|||
assert.ok($('.tooltip').is('.fade.show'), '200ms: tooltip still faded active') |
|||
done() |
|||
}, 200) |
|||
}, 0) |
|||
|
|||
$tooltip.trigger('mouseenter') |
|||
}) |
|||
|
|||
QUnit.test('should not show tooltip if leave event occurs before delay expires', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
|
|||
var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip({ delay: 150 }) |
|||
|
|||
setTimeout(function () { |
|||
assert.ok(!$('.tooltip').is('.fade.show'), '100ms: tooltip not faded active') |
|||
$tooltip.trigger('mouseout') |
|||
}, 100) |
|||
|
|||
setTimeout(function () { |
|||
assert.ok(!$('.tooltip').is('.fade.show'), '200ms: tooltip not faded active') |
|||
done() |
|||
}, 200) |
|||
|
|||
$tooltip.trigger('mouseenter') |
|||
}) |
|||
|
|||
QUnit.test('should not show tooltip if leave event occurs before delay expires, even if hide delay is 0', function (assert) { |
|||
assert.expect(2) |
|||
var done = assert.async() |
|||
|
|||
var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip({ delay: { show: 150, hide: 0 } }) |
|||
|
|||
setTimeout(function () { |
|||
assert.ok(!$('.tooltip').is('.fade.show'), '100ms: tooltip not faded active') |
|||
$tooltip.trigger('mouseout') |
|||
}, 100) |
|||
|
|||
setTimeout(function () { |
|||
assert.ok(!$('.tooltip').is('.fade.show'), '250ms: tooltip not faded active') |
|||
done() |
|||
}, 250) |
|||
|
|||
$tooltip.trigger('mouseenter') |
|||
}) |
|||
|
|||
QUnit.test('should wait 200ms before hiding the tooltip', function (assert) { |
|||
assert.expect(3) |
|||
var done = assert.async() |
|||
|
|||
var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip({ delay: { show: 0, hide: 150 } }) |
|||
|
|||
setTimeout(function () { |
|||
assert.ok($($tooltip.data('bs.tooltip').tip).is('.fade.show'), '1ms: tooltip faded active') |
|||
|
|||
$tooltip.trigger('mouseout') |
|||
|
|||
setTimeout(function () { |
|||
assert.ok($($tooltip.data('bs.tooltip').tip).is('.fade.show'), '100ms: tooltip still faded active') |
|||
}, 100) |
|||
|
|||
setTimeout(function () { |
|||
assert.ok(!$($tooltip.data('bs.tooltip').tip).is('.show'), '200ms: tooltip removed') |
|||
done() |
|||
}, 200) |
|||
|
|||
}, 0) |
|||
|
|||
$tooltip.trigger('mouseenter') |
|||
}) |
|||
|
|||
QUnit.test('should correctly position tooltips on SVG elements', function (assert) { |
|||
if (!window.SVGElement) { |
|||
// Skip IE8 since it doesn't support SVG
|
|||
assert.expect(0) |
|||
return |
|||
} |
|||
assert.expect(2) |
|||
|
|||
var done = assert.async() |
|||
|
|||
var styles = '<style>' |
|||
+ '.tooltip, .tooltip *, .tooltip *:before, .tooltip *:after { box-sizing: border-box; }' |
|||
+ '.tooltip { position: absolute; }' |
|||
+ '.tooltip .tooltip-inner { width: 24px; height: 24px; font-family: Helvetica; }' |
|||
+ '</style>' |
|||
var $styles = $(styles).appendTo('head') |
|||
|
|||
$('#qunit-fixture').append( |
|||
'<div style="position: fixed; top: 0; left: 0;">' |
|||
+ ' <svg width="200" height="200">' |
|||
+ ' <circle cx="100" cy="100" r="10" title="m" id="theCircle" />' |
|||
+ ' </svg>' |
|||
+ '</div>') |
|||
var $circle = $('#theCircle') |
|||
|
|||
$circle |
|||
.on('shown.bs.tooltip', function () { |
|||
var offset = $('.tooltip').offset() |
|||
$styles.remove() |
|||
assert.ok(Math.abs(offset.left - 88) <= 1, 'tooltip has correct horizontal location') |
|||
$circle.bootstrapTooltip('hide') |
|||
assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom') |
|||
done() |
|||
}) |
|||
.bootstrapTooltip({ placement: 'top', trigger: 'manual' }) |
|||
|
|||
$circle.bootstrapTooltip('show') |
|||
}) |
|||
|
|||
QUnit.test('should not reload the tooltip on subsequent mouseenter events', function (assert) { |
|||
assert.expect(1) |
|||
var titleHtml = function () { |
|||
var uid = Util.getUID('tooltip') |
|||
return '<p id="tt-content">' + uid + '</p><p>' + uid + '</p><p>' + uid + '</p>' |
|||
} |
|||
|
|||
var $tooltip = $('<span id="tt-outer" rel="tooltip" data-trigger="hover" data-placement="top">some text</span>') |
|||
.appendTo('#qunit-fixture') |
|||
|
|||
$tooltip.bootstrapTooltip({ |
|||
html: true, |
|||
animation: false, |
|||
trigger: 'hover', |
|||
delay: { show: 0, hide: 500 }, |
|||
container: $tooltip, |
|||
title: titleHtml |
|||
}) |
|||
|
|||
$('#tt-outer').trigger('mouseenter') |
|||
|
|||
var currentUid = $('#tt-content').text() |
|||
|
|||
$('#tt-content').trigger('mouseenter') |
|||
assert.strictEqual(currentUid, $('#tt-content').text()) |
|||
}) |
|||
|
|||
QUnit.test('should not reload the tooltip if the mouse leaves and re-enters before hiding', function (assert) { |
|||
assert.expect(4) |
|||
|
|||
var titleHtml = function () { |
|||
var uid = Util.getUID('tooltip') |
|||
return '<p id="tt-content">' + uid + '</p><p>' + uid + '</p><p>' + uid + '</p>' |
|||
} |
|||
|
|||
var $tooltip = $('<span id="tt-outer" rel="tooltip" data-trigger="hover" data-placement="top">some text</span>') |
|||
.appendTo('#qunit-fixture') |
|||
|
|||
$tooltip.bootstrapTooltip({ |
|||
html: true, |
|||
animation: false, |
|||
trigger: 'hover', |
|||
delay: { show: 0, hide: 500 }, |
|||
title: titleHtml |
|||
}) |
|||
|
|||
var obj = $tooltip.data('bs.tooltip') |
|||
|
|||
$('#tt-outer').trigger('mouseenter') |
|||
|
|||
var currentUid = $('#tt-content').text() |
|||
|
|||
$('#tt-outer').trigger('mouseleave') |
|||
assert.strictEqual(currentUid, $('#tt-content').text()) |
|||
|
|||
assert.ok(obj._hoverState === 'out', 'the tooltip hoverState should be set to "out"') |
|||
|
|||
$('#tt-outer').trigger('mouseenter') |
|||
assert.ok(obj._hoverState === 'show', 'the tooltip hoverState should be set to "show"') |
|||
|
|||
assert.strictEqual(currentUid, $('#tt-content').text()) |
|||
}) |
|||
|
|||
QUnit.test('should correctly position tooltips on transformed elements', function (assert) { |
|||
var styleProps = document.documentElement.style |
|||
if (!('transform' in styleProps) && !('webkitTransform' in styleProps) && !('msTransform' in styleProps)) { |
|||
assert.expect(0) |
|||
return |
|||
} |
|||
assert.expect(2) |
|||
|
|||
var done = assert.async() |
|||
|
|||
var styles = '<style>' |
|||
+ '#qunit-fixture { top: 0; left: 0; }' |
|||
+ '.tooltip, .tooltip *, .tooltip *:before, .tooltip *:after { box-sizing: border-box; }' |
|||
+ '.tooltip { position: absolute; }' |
|||
+ '.tooltip .tooltip-inner { width: 24px; height: 24px; font-family: Helvetica; }' |
|||
+ '#target { position: absolute; top: 100px; left: 50px; width: 100px; height: 200px; -webkit-transform: rotate(270deg); -ms-transform: rotate(270deg); transform: rotate(270deg); }' |
|||
+ '</style>' |
|||
var $styles = $(styles).appendTo('head') |
|||
|
|||
var $element = $('<div id="target" title="1"/>').appendTo('#qunit-fixture') |
|||
|
|||
$element |
|||
.on('shown.bs.tooltip', function () { |
|||
var offset = $('.tooltip').offset() |
|||
$styles.remove() |
|||
assert.ok(Math.abs(offset.left - 88) <= 1, 'tooltip has correct horizontal location') |
|||
assert.ok(Math.abs(offset.top - 126) <= 1, 'tooltip has correct vertical location') |
|||
$element.bootstrapTooltip('hide') |
|||
done() |
|||
}) |
|||
.bootstrapTooltip({ |
|||
trigger: 'manual' |
|||
}) |
|||
|
|||
$element.bootstrapTooltip('show') |
|||
}) |
|||
|
|||
QUnit.test('should do nothing when an attempt is made to hide an uninitialized tooltip', function (assert) { |
|||
assert.expect(1) |
|||
|
|||
var $tooltip = $('<span data-toggle="tooltip" title="some tip">some text</span>') |
|||
.appendTo('#qunit-fixture') |
|||
.on('hidden.bs.tooltip shown.bs.tooltip', function () { |
|||
assert.ok(false, 'should not fire any tooltip events') |
|||
}) |
|||
.bootstrapTooltip('hide') |
|||
assert.strictEqual($tooltip.data('bs.tooltip'), undefined, 'should not initialize the tooltip') |
|||
}) |
|||
|
|||
QUnit.test('should not remove tooltip if multiple triggers are set and one is still active', function (assert) { |
|||
assert.expect(41) |
|||
var $el = $('<button>Trigger</button>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip({ trigger: 'click hover focus', animation: false }) |
|||
var tooltip = $el.data('bs.tooltip') |
|||
var $tooltip = $(tooltip.getTipElement()) |
|||
|
|||
function showingTooltip() { return $tooltip.hasClass('show') || tooltip._hoverState === 'show' } |
|||
|
|||
var tests = [ |
|||
['mouseenter', 'mouseleave'], |
|||
|
|||
['focusin', 'focusout'], |
|||
|
|||
['click', 'click'], |
|||
|
|||
['mouseenter', 'focusin', 'focusout', 'mouseleave'], |
|||
['mouseenter', 'focusin', 'mouseleave', 'focusout'], |
|||
|
|||
['focusin', 'mouseenter', 'mouseleave', 'focusout'], |
|||
['focusin', 'mouseenter', 'focusout', 'mouseleave'], |
|||
|
|||
['click', 'focusin', 'mouseenter', 'focusout', 'mouseleave', 'click'], |
|||
['mouseenter', 'click', 'focusin', 'focusout', 'mouseleave', 'click'], |
|||
['mouseenter', 'focusin', 'click', 'click', 'mouseleave', 'focusout'] |
|||
] |
|||
|
|||
assert.ok(!showingTooltip()) |
|||
|
|||
$.each(tests, function (idx, triggers) { |
|||
for (var i = 0, len = triggers.length; i < len; i++) { |
|||
$el.trigger(triggers[i]) |
|||
assert.equal(i < len - 1, showingTooltip()) |
|||
} |
|||
}) |
|||
}) |
|||
|
|||
QUnit.test('should show on first trigger after hide', function (assert) { |
|||
assert.expect(3) |
|||
var $el = $('<a href="#" rel="tooltip" title="Test tooltip"/>') |
|||
.appendTo('#qunit-fixture') |
|||
.bootstrapTooltip({ trigger: 'click hover focus', animation: false }) |
|||
|
|||
var tooltip = $el.data('bs.tooltip') |
|||
var $tooltip = $(tooltip.getTipElement()) |
|||
|
|||
function showingTooltip() { return $tooltip.hasClass('show') || tooltip._hoverState === 'show' } |
|||
|
|||
$el.trigger('click') |
|||
assert.ok(showingTooltip(), 'tooltip is faded in') |
|||
|
|||
$el.bootstrapTooltip('hide') |
|||
assert.ok(!showingTooltip(), 'tooltip was faded out') |
|||
|
|||
$el.trigger('click') |
|||
assert.ok(showingTooltip(), 'tooltip is faded in again') |
|||
}) |
|||
|
|||
QUnit.test('should hide tooltip when their containing modal is closed', function (assert) { |
|||
assert.expect(1) |
|||
var done = assert.async() |
|||
var templateHTML = '<div id="modal-test" class="modal">' + |
|||
'<div class="modal-dialog" role="document">' + |
|||
'<div class="modal-content">' + |
|||
'<div class="modal-body">' + |
|||
'<a id="tooltipTest" href="#" data-toggle="tooltip" title="Some tooltip text!">Tooltip</a>' + |
|||
'</div>' + |
|||
'</div>' + |
|||
'</div>' + |
|||
'</div>' |
|||
|
|||
$(templateHTML).appendTo('#qunit-fixture') |
|||
$('#tooltipTest') |
|||
.bootstrapTooltip({ trigger: 'manuel' }) |
|||
.on('shown.bs.tooltip', function () { |
|||
$('#modal-test').modal('hide') |
|||
}) |
|||
.on('hide.bs.tooltip', function () { |
|||
assert.ok(true, 'tooltip hide') |
|||
done() |
|||
}) |
|||
|
|||
$('#modal-test') |
|||
.on('shown.bs.modal', function () { |
|||
$('#tooltipTest').bootstrapTooltip('show') |
|||
}) |
|||
.modal('show') |
|||
}) |
|||
}) |
File diff suppressed because it is too large
@ -1,4 +0,0 @@ |
|||
// Bootstrap overrides |
|||
// |
|||
// Copy variables from `_variables.scss` to this file to override default values |
|||
// without modifying source files. |
@ -0,0 +1,86 @@ |
|||
// Bootstrap functions |
|||
// |
|||
// Utility mixins and functions for evalutating source code across our variables, maps, and mixins. |
|||
|
|||
// Ascending |
|||
// Used to evaluate Sass maps like our grid breakpoints. |
|||
@mixin _assert-ascending($map, $map-name) { |
|||
$prev-key: null; |
|||
$prev-num: null; |
|||
@each $key, $num in $map { |
|||
@if $prev-num == null { |
|||
// Do nothing |
|||
} @else if not comparable($prev-num, $num) { |
|||
@warn "Potentially invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} whose unit makes it incomparable to #{$prev-num}, the value of the previous key '#{$prev-key}' !"; |
|||
} @else if $prev-num >= $num { |
|||
@warn "Invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} which isn't greater than #{$prev-num}, the value of the previous key '#{$prev-key}' !"; |
|||
} |
|||
$prev-key: $key; |
|||
$prev-num: $num; |
|||
} |
|||
} |
|||
|
|||
// Starts at zero |
|||
// Another grid mixin that ensures the min-width of the lowest breakpoint starts at 0. |
|||
@mixin _assert-starts-at-zero($map) { |
|||
$values: map-values($map); |
|||
$first-value: nth($values, 1); |
|||
@if $first-value != 0 { |
|||
@warn "First breakpoint in `$grid-breakpoints` must start at 0, but starts at #{$first-value}."; |
|||
} |
|||
} |
|||
|
|||
// Replace `$search` with `$replace` in `$string` |
|||
// Used on our SVG icon backgrounds for custom forms. |
|||
// |
|||
// @author Hugo Giraudel |
|||
// @param {String} $string - Initial string |
|||
// @param {String} $search - Substring to replace |
|||
// @param {String} $replace ('') - New value |
|||
// @return {String} - Updated string |
|||
@function str-replace($string, $search, $replace: "") { |
|||
$index: str-index($string, $search); |
|||
|
|||
@if $index { |
|||
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace); |
|||
} |
|||
|
|||
@return $string; |
|||
} |
|||
|
|||
// Color contrast |
|||
@function color-yiq($color) { |
|||
$r: red($color); |
|||
$g: green($color); |
|||
$b: blue($color); |
|||
|
|||
$yiq: (($r * 299) + ($g * 587) + ($b * 114)) / 1000; |
|||
|
|||
@if ($yiq >= $yiq-contrasted-threshold) { |
|||
@return $yiq-text-dark; |
|||
} @else { |
|||
@return $yiq-text-light; |
|||
} |
|||
} |
|||
|
|||
// Retrieve color Sass maps |
|||
@function color($key: "blue") { |
|||
@return map-get($colors, $key); |
|||
} |
|||
|
|||
@function theme-color($key: "primary") { |
|||
@return map-get($theme-colors, $key); |
|||
} |
|||
|
|||
@function gray($key: "100") { |
|||
@return map-get($grays, $key); |
|||
} |
|||
|
|||
// Request a theme color level |
|||
@function theme-color-level($color-name: "primary", $level: 0) { |
|||
$color: theme-color($color-name); |
|||
$color-base: if($level > 0, #000, #fff); |
|||
$level: abs($level); |
|||
|
|||
@return mix($color-base, $color, $level * $theme-color-interval); |
|||
} |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue