diff --git a/.babelrc.js b/.babelrc.js new file mode 100644 index 0000000..6630074 --- /dev/null +++ b/.babelrc.js @@ -0,0 +1,17 @@ +module.exports = { + presets: [ + [ + '@babel/env', + { + loose: true, + modules: false, + exclude: [ + 'transform-typeof-symbol' + ] + } + ] + ], + plugins: [ + '@babel/proposal-object-rest-spread' + ] +}; diff --git a/.gitattributes b/.gitattributes index 3188deb..adbc29b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1,5 @@ # Export-ignore files (GitHub download link, composer [--prefer-dist]) -# Dont add bower.json, otherwise it is not loaded in the Bower package docs export-ignore .* export-ignore -Gruntfile.js export-ignore README.md export-ignore package.json export-ignore diff --git a/.gitignore b/.gitignore index 322b72b..310c082 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,5 @@ *-dist.zip # Folders to ignore -_gh_pages +docs/_site node_modules diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index 5f24198..0000000 --- a/Gruntfile.js +++ /dev/null @@ -1,202 +0,0 @@ -/*! - * Bootstrap-submenu's Gruntfile - * http://vsn4ik.github.io/bootstrap-submenu - * Copyright 2014-2018 Vasilii A. (https://github.com/vsn4ik) - * Licensed under the MIT license - */ - -'use strict'; - -module.exports = function(grunt) { - // Force use of Unix newlines - grunt.util.linefeed = '\n'; - - grunt.initConfig({ - pkg: grunt.file.readJSON('package.json'), - year: grunt.template.today('yyyy'), - clean: { - dist: [ - 'dist', - '*-dist.zip' - ], - docs: '_gh_pages/*' - }, - less: { - options: { - paths: ['node_modules'] - }, - core: { - options: { - sourceMap: true, - sourceMapURL: '<%= pkg.name %>.css.map', - outputSourceFiles: true - }, - src: 'less/<%= pkg.name %>.less', - dest: 'dist/css/<%= pkg.name %>.css' - }, - docs: { - src: 'docs/assets/less/docs.less', - dest: 'docs/assets/css/docs.css' - } - }, - copy: { - core: { - src: 'js/*', - dest: 'dist/' - }, - assets: { - files: [{ - expand: true, - src: 'dist/**', - dest: '_gh_pages/' - }, { - expand: true, - cwd: 'docs', - src: 'assets/**', - dest: '_gh_pages' - }, { - expand: true, - cwd: 'node_modules/bootstrap/dist', - src: '**', - dest: '_gh_pages/vendor/bootstrap' - }, { - expand: true, - cwd: 'node_modules/highlight.js/styles', - src: '*', - dest: '_gh_pages/vendor/highlight.js/css' - }, { - expand: true, - cwd: 'node_modules/jquery/dist', - src: 'jquery.js', - dest: '_gh_pages/vendor/jquery/js' - }, { - expand: true, - cwd: 'node_modules/font-awesome', - src: '{css,fonts}/*', - dest: '_gh_pages/vendor/font-awesome' - }] - } - }, - cssmin: { - core: { - options: { - compatibility: 'ie8' - }, - expand: true, - src: 'dist/css/*.css', - ext: '.min.css' - } - }, - jshint: { - options: { - curly: true, - globalstrict: true, - latedef: true, - node: true, - noempty: true, - strict: true, - unused: true, - boss: true - }, - core: { - options: { - devel: true, - jquery: true, - globals: { - define: true - } - }, - src: 'js/' - }, - grunt: 'Gruntfile.js', - docs: { - options: { - jquery: true, - browser: true, - globals: { - hljs: true - } - }, - src: 'docs/assets/js/' - } - }, - jscs: { - options: { - config: 'js/.jscsrc' - }, - core: 'js/', - grunt: 'Gruntfile.js', - docs: { - src: 'docs/assets/js/' - } - }, - uglify: { - core: { - expand: true, - src: 'dist/js/*.js', - ext: '.min.js' - } - }, - usebanner: { - options: { - banner: [ - '/*!', - ' * <%= pkg.name.charAt(0).toUpperCase() + pkg.name.slice(1) %> v<%= pkg.version %> (<%= pkg.homepage %>)', - ' * Copyright 2014-<%= year %> <%= pkg.author.name %> (<%= pkg.author.url %>)', - ' * Licensed under the <%= pkg.license %> license', - ' */' - ].join('\n') + '\n' - }, - dist: 'dist/*/*.{css,js}' - }, - ejs: { - docs: { - options: { - pkg: '<%= pkg %>', - year: '<%= year %>' - }, - expand: true, - cwd: 'docs', - src: 'index.html', - dest: '_gh_pages/' - } - }, - compress: { - dist: { - options: { - archive: '<%= compress.dist.dest %>.zip' - }, - expand: true, - cwd: 'dist', - src: '**', - dest: '<%= pkg.name %>-<%= pkg.version %>-dist' - } - } - }); - - // These plugins provide necessary tasks. - require('load-grunt-tasks')(grunt, { - scope: 'devDependencies' - }); - - grunt.registerTask('default', [ - 'clean', - 'less:core', - 'cssmin', - 'jshint', - 'jscs', - 'copy:core', - 'uglify', - 'usebanner' - ]); - - grunt.registerTask('docs', [ - 'ejs', - 'less:docs', - 'copy:assets' - ]); - - grunt.registerTask('release-zip', [ - 'compress' - ]); -}; diff --git a/README.md b/README.md index 996f905..0735d96 100644 --- a/README.md +++ b/README.md @@ -10,12 +10,10 @@ Several quick start options are available: -* [Download the latest release](https://github.com/vsn4ik/bootstrap-submenu/archive/v2.0.4.zip "Download Bootstrap-submenu"). -* Clone the repo: `git clone https://github.com/vsn4ik/bootstrap-submenu.git`. -* Install with [npm](https://www.npmjs.com): `npm install bootstrap-submenu`. -* Install with [yarn](https://yarnpkg.com): `yarn add bootstrap-submenu`. -* Install with [Bower](https://bower.io): `bower install bootstrap-submenu` (deprecated on v2.0.5, removed on 2018'Q2). -* Install with [Composer](https://getcomposer.org): `composer require vsn4ik/bootstrap-submenu "dev-master"` (deprecated on v.2.0.5, removed on 2018'Q2). +* [Download the latest release](https://github.com/vsn4ik/bootstrap-submenu/archive/v3.0.0.zip "Download Bootstrap-submenu") +* Clone the repo: `git clone https://github.com/vsn4ik/bootstrap-submenu.git` +* Install with [npm](https://www.npmjs.com): `npm install bootstrap-submenu` +* Install with [yarn](https://yarnpkg.com): `yarn add bootstrap-submenu` ### What's included @@ -38,7 +36,7 @@ For some working examples, visit our [examples](https://vsn4ik.github.io/bootstr ## Min Requirements -* Bootstrap 3.0.0 +* Bootstrap 4.1.0 * jQuery 1.9.1 diff --git a/composer.json b/composer.json deleted file mode 100644 index 9b81b9d..0000000 --- a/composer.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "vsn4ik/bootstrap-submenu", - "description": "Bootstrap Sub-Menus", - "keywords": [ - "bootstrap", - "dropdown", - "jquery-plugin", - "submenu" - ], - "homepage": "https://vsn4ik.github.io/bootstrap-submenu", - "authors": [ - { - "name": "Vasilii A.", - "homepage": "https://github.com/vsn4ik" - } - ], - "license": "MIT" -} diff --git a/css/bootstrap-submenu.css b/css/bootstrap-submenu.css new file mode 100644 index 0000000..8c76602 --- /dev/null +++ b/css/bootstrap-submenu.css @@ -0,0 +1,29 @@ +.dropdown-submenu.dropright .dropdown-menu { + margin-left: 1px; +} + +.dropdown-submenu.dropleft .dropdown-menu { + margin-right: 1px; +} + +[x-placement^="bottom-"] .dropdown-submenu .dropdown-menu, +.navbar .dropdown-submenu .dropdown-menu { + bottom: auto; + margin-top: calc(-0.5rem - 1px); +} + +[x-placement^="top-"] .dropdown-submenu .dropdown-menu { + top: auto; + bottom: 0; + margin-bottom: calc(-0.5rem - 1px); +} + +.dropdown-submenu.dropright > .dropdown-toggle { + display: flex; + justify-content: space-between; + align-items: center; +} + +.dropdown-submenu.dropright > .dropdown-toggle::after { + margin-right: -12px; +} diff --git a/dist/css/bootstrap-submenu.css b/dist/css/bootstrap-submenu.css index df7ae15..8c76602 100644 --- a/dist/css/bootstrap-submenu.css +++ b/dist/css/bootstrap-submenu.css @@ -1,125 +1,29 @@ -/*! - * Bootstrap-submenu v2.0.4 (https://vsn4ik.github.io/bootstrap-submenu/) - * Copyright 2014-2018 Vasilii A. (https://github.com/vsn4ik) - * Licensed under the MIT license - */ +.dropdown-submenu.dropright .dropdown-menu { + margin-left: 1px; +} + +.dropdown-submenu.dropleft .dropdown-menu { + margin-right: 1px; +} -.dropdown-submenu > a:after { - content: ""; +[x-placement^="bottom-"] .dropdown-submenu .dropdown-menu, +.navbar .dropdown-submenu .dropdown-menu { + bottom: auto; + margin-top: calc(-0.5rem - 1px); } -@media (min-width: 768px) { - .dropdown-submenu { - position: relative; - } - .dropdown-submenu .dropdown-menu { - top: 0; - left: 100%; - margin-top: -6px; - border-top-left-radius: 0; - } - .dropup .dropdown-submenu .dropdown-menu, - .navbar-fixed-bottom .dropdown-submenu .dropdown-menu { - top: auto; - bottom: 0; - margin-top: 0; - margin-bottom: -6px; - border-top-left-radius: 4px; - border-bottom-left-radius: 0; - } - .dropdown-menu-right .dropdown-submenu .dropdown-menu, - .navbar-right .dropdown-submenu .dropdown-menu { - left: auto; - right: 100%; - border-top-left-radius: 4px; - border-top-right-radius: 0; - } - .dropup .dropdown-menu-right .dropdown-submenu .dropdown-menu, - .dropup .navbar-right .dropdown-submenu .dropdown-menu, - .navbar-fixed-bottom .dropdown-menu-right .dropdown-submenu .dropdown-menu, - .navbar-fixed-bottom .navbar-right .dropdown-submenu .dropdown-menu { - border-radius: 4px 4px 0; - } - .dropdown-submenu > a:after { - float: right; - margin-top: 6px; - margin-right: -10px; - border-left: 4px dashed; - border-top: 4px solid transparent; - border-bottom: 4px solid transparent; - } - .dropdown-menu-right .dropdown-submenu > a:after, - .navbar-right .dropdown-submenu > a:after { - float: left; - border-left: none; - margin-left: -10px; - margin-right: 0; - border-right: 4px dashed; - border-top: 4px solid transparent; - border-bottom: 4px solid transparent; - } + +[x-placement^="top-"] .dropdown-submenu .dropdown-menu { + top: auto; + bottom: 0; + margin-bottom: calc(-0.5rem - 1px); } -@media (max-width: 767px) { - .dropdown-submenu .dropdown-menu { - position: static; - margin-top: 0; - border: 0; - box-shadow: none; - } - .dropdown-submenu > a:after { - margin-left: 6px; - display: inline-block; - vertical-align: middle; - border-top: 4px dashed; - border-left: 4px solid transparent; - border-right: 4px solid transparent; - } - .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li.dropdown-header, - .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li.dropdown-header, - .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li.dropdown-header, - .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > a, - .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > a, - .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > a { - padding-left: 30px; - } - .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li.dropdown-header, - .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li.dropdown-header, - .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li.dropdown-header, - .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > a, - .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > a, - .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > a { - padding-left: 40px; - } - .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header, - .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header, - .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header, - .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a, - .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a, - .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a { - padding-left: 50px; - } - .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header, - .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header, - .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header, - .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a, - .dropup > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a, - .btn-group > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a { - padding-left: 60px; - } - .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li.dropdown-header, - .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > a { - padding-left: 35px; - } - .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li.dropdown-header, - .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > a { - padding-left: 45px; - } - .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header, - .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a { - padding-left: 55px; - } - .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li.dropdown-header, - .navbar-nav > .dropdown > .dropdown-menu > .dropdown-submenu > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > .dropdown-menu > li > a { - padding-left: 65px; - } + +.dropdown-submenu.dropright > .dropdown-toggle { + display: flex; + justify-content: space-between; + align-items: center; +} + +.dropdown-submenu.dropright > .dropdown-toggle::after { + margin-right: -12px; } -/*# sourceMappingURL=bootstrap-submenu.css.map */ \ No newline at end of file diff --git a/dist/css/bootstrap-submenu.css.map b/dist/css/bootstrap-submenu.css.map deleted file mode 100644 index fd3a27e..0000000 --- a/dist/css/bootstrap-submenu.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["less/bootstrap-submenu.less","less/mixins.less"],"names":[],"mappings":"AAYA,iBAAkB,IAAG;EACnB,SAAS,EAAT;;AAGF,QAA2C;EACzC;IACE,kBAAA;;EADF,iBAGE;IACE,MAAA;IACA,UAAA;IACA,gBAAA;IACA,yBAAA;;EAGA,OAAQ,kBAPV;EAQE,oBAAqB,kBARvB;IASI,SAAA;IACA,SAAA;IACA,aAAA;IACA,mBAAA;IACA,2BAAA;IACA,4BAAA;;EAGF,oBAAqB,kBAjBvB;EAkBE,aAAc,kBAlBhB;IAmBI,UAAA;IACA,WAAA;IAEA,2BAAA;IACA,0BAAA;;EAEA,OAAQ,qBARW,kBAjBvB;EAyBI,OAAQ,cAPI,kBAlBhB;EA0BI,oBAAqB,qBATF,kBAjBvB;EA0BI,oBAAqB,cART,kBAlBhB;IA2BM,wBAAA;;EA9BR,iBAmCE,IAAG;IACD,YAAA;IACA,eAAA;IACA,mBAAA;ICrDJ,uBAAA;IAEA,iCAAA;IACA,oCAAA;;EDsDI,oBAAqB,kBAPvB,IAAG;EAQD,aAAc,kBARhB,IAAG;IASC,WAAA;IACA,iBAAA;IACA,kBAAA;IACA,eAAA;IC9DN,wBAAA;IAEA,iCAAA;IACA,oCAAA;;;ADmEF,QAA+C;EAC7C,iBACE;IACE,gBAAA;IACA,aAAA;IACA,SAAA;IACA,gBAAA;;EALJ,iBAQE,IAAG;IACD,gBAAA;IACA,qBAAA;IACA,sBAAA;IClFJ,sBAAA;IAEA,kCAAA;IACA,mCAAA;;EAKE,SDiFU,iBADG,oBCjFf,iBAAiB,KACd;EAAD,ODkFQ,iBAFK,oBCjFf,iBAAiB,KACd;EAAD,UDmFW,iBAHE,oBCjFf,iBAAiB,KACd;EDiFD,SAAU,iBADG,oBCjFf,iBAAiB,KAEf;EDiFA,OAAQ,iBAFK,oBCjFf,iBAAiB,KAEf;EDkFA,UAAW,iBAHE,oBCjFf,iBAAiB,KAEf;IACE,kBAAA;;EAFF,SDiFU,iBADG,oBCjFf,iBAAiB,KAAjB,iBAAiB,KACd;EAAD,ODkFQ,iBAFK,oBCjFf,iBAAiB,KAAjB,iBAAiB,KACd;EAAD,UDmFW,iBAHE,oBCjFf,iBAAiB,KAAjB,iBAAiB,KACd;EDiFD,SAAU,iBADG,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAEf;EDiFA,OAAQ,iBAFK,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAEf;EDkFA,UAAW,iBAHE,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAEf;IACE,kBAAA;;EAFF,SDiFU,iBADG,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KACd;EAAD,ODkFQ,iBAFK,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KACd;EAAD,UDmFW,iBAHE,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KACd;EDiFD,SAAU,iBADG,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAEf;EDiFA,OAAQ,iBAFK,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAEf;EDkFA,UAAW,iBAHE,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAEf;IACE,kBAAA;;EAFF,SDiFU,iBADG,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KACd;EAAD,ODkFQ,iBAFK,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KACd;EAAD,UDmFW,iBAHE,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KACd;EDiFD,SAAU,iBADG,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAEf;EDiFA,OAAQ,iBAFK,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAEf;EDkFA,UAAW,iBAHE,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAEf;IACE,kBAAA;;EAFF,WDuFY,YAAY,iBAPX,oBCjFf,iBAAiB,KACd;EDuFD,WAAY,YAAY,iBAPX,oBCjFf,iBAAiB,KAEf;IACE,kBAAA;;EAFF,WDuFY,YAAY,iBAPX,oBCjFf,iBAAiB,KAAjB,iBAAiB,KACd;EDuFD,WAAY,YAAY,iBAPX,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAEf;IACE,kBAAA;;EAFF,WDuFY,YAAY,iBAPX,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KACd;EDuFD,WAAY,YAAY,iBAPX,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAEf;IACE,kBAAA;;EAFF,WDuFY,YAAY,iBAPX,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KACd;EDuFD,WAAY,YAAY,iBAPX,oBCjFf,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAAjB,iBAAiB,KAEf;IACE,kBAAA","sourcesContent":["// :: friends with IE8. Use :: in future.\n\n@import \"bootstrap/less/variables.less\";\n@import \"mixins.less\";\n\n// Variables\n@caret-margin: -@caret-width-base * 2 - 2;\n\n//\n// Sub-Menus\n// --------------------------------------------------\n\n.dropdown-submenu > a:after {\n content: \"\";\n}\n\n@media (min-width: @grid-float-breakpoint) {\n .dropdown-submenu {\n position: relative;\n\n .dropdown-menu {\n top: 0;\n left: 100%;\n margin-top: -6px;\n border-top-left-radius: 0;\n\n // Strictly before .dropdown-menu-right\n .dropup &,\n .navbar-fixed-bottom & {\n top: auto;\n bottom: 0;\n margin-top: 0;\n margin-bottom: -6px;\n border-top-left-radius: @border-radius-base;\n border-bottom-left-radius: 0;\n }\n\n .dropdown-menu-right &,\n .navbar-right & {\n left: auto;\n right: 100%;\n\n border-top-left-radius: @border-radius-base;\n border-top-right-radius: 0;\n\n .dropup &,\n .navbar-fixed-bottom & {\n border-radius: @border-radius-base @border-radius-base 0;\n }\n }\n }\n\n > a:after {\n float: right;\n margin-top: @line-height-computed / 2 - @caret-width-base;\n margin-right: @caret-margin;\n\n .make-caret(left, top, bottom);\n\n .dropdown-menu-right &,\n .navbar-right & {\n float: left;\n border-left: none;\n margin-left: @caret-margin;\n margin-right: 0;\n\n .make-caret(right, top, bottom);\n }\n }\n }\n}\n\n@media (max-width: @grid-float-breakpoint-max) {\n .dropdown-submenu {\n .dropdown-menu {\n position: static;\n margin-top: 0;\n border: 0;\n box-shadow: none;\n }\n\n > a:after {\n margin-left: 6px;\n display: inline-block;\n vertical-align: middle;\n\n .make-caret(top, left, right);\n }\n }\n\n .dropdown-menu > .dropdown-submenu {\n .dropdown > &,\n .dropup > &,\n .btn-group > & {\n .make-nested-list(30px, 0, 4);\n }\n\n .navbar-nav > .dropdown > & {\n .make-nested-list(35px, 0, 4);\n }\n }\n}\n",".make-caret(@base, @left, @right) {\n // dashed: fix caret size for Mozilla Firefox\n border-@{base}: @caret-width-base dashed;\n\n border-@{left}: @caret-width-base solid transparent;\n border-@{right}: @caret-width-base solid transparent;\n}\n\n.make-nested-list(@offset, @i, @n) when (@i < @n) {\n > .dropdown-menu > li {\n &.dropdown-header,\n > a {\n padding-left: @offset + (10 * @i);\n }\n\n .make-nested-list(@offset, @i + 1, @n);\n }\n}\n"]} \ No newline at end of file diff --git a/dist/css/bootstrap-submenu.min.css b/dist/css/bootstrap-submenu.min.css index dd44c6e..5c635d6 100644 --- a/dist/css/bootstrap-submenu.min.css +++ b/dist/css/bootstrap-submenu.min.css @@ -1,7 +1,2 @@ -/*! - * Bootstrap-submenu v2.0.4 (https://vsn4ik.github.io/bootstrap-submenu/) - * Copyright 2014-2018 Vasilii A. (https://github.com/vsn4ik) - * Licensed under the MIT license - */ - -.dropdown-submenu>a:after{content:""}@media (min-width:768px){.dropdown-submenu{position:relative}.dropdown-submenu .dropdown-menu{top:0;left:100%;margin-top:-6px;border-top-left-radius:0}.dropup .dropdown-submenu .dropdown-menu,.navbar-fixed-bottom .dropdown-submenu .dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-6px;border-top-left-radius:4px;border-bottom-left-radius:0}.dropdown-menu-right .dropdown-submenu .dropdown-menu,.navbar-right .dropdown-submenu .dropdown-menu{left:auto;right:100%;border-top-left-radius:4px;border-top-right-radius:0}.dropup .dropdown-menu-right .dropdown-submenu .dropdown-menu,.dropup .navbar-right .dropdown-submenu .dropdown-menu,.navbar-fixed-bottom .dropdown-menu-right .dropdown-submenu .dropdown-menu,.navbar-fixed-bottom .navbar-right .dropdown-submenu .dropdown-menu{border-radius:4px 4px 0}.dropdown-submenu>a:after{float:right;margin-top:6px;margin-right:-10px;border-left:4px dashed;border-top:4px solid transparent;border-bottom:4px solid transparent}.dropdown-menu-right .dropdown-submenu>a:after,.navbar-right .dropdown-submenu>a:after{float:left;border-left:none;margin-left:-10px;margin-right:0;border-right:4px dashed;border-top:4px solid transparent;border-bottom:4px solid transparent}}@media (max-width:767px){.dropdown-submenu .dropdown-menu{position:static;margin-top:0;border:0;box-shadow:none}.dropdown-submenu>a:after{margin-left:6px;display:inline-block;vertical-align:middle;border-top:4px dashed;border-left:4px solid transparent;border-right:4px solid transparent}.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li.dropdown-header,.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>a,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li.dropdown-header,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>a,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li.dropdown-header,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>a{padding-left:30px}.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>a,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>a,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>a{padding-left:40px}.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a{padding-left:50px}.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.btn-group>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.dropup>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a{padding-left:60px}.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li.dropdown-header,.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>a{padding-left:35px}.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>a{padding-left:45px}.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a{padding-left:55px}.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li.dropdown-header,.navbar-nav>.dropdown>.dropdown-menu>.dropdown-submenu>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>.dropdown-menu>li>a{padding-left:65px}} \ No newline at end of file +.dropdown-submenu.dropright .dropdown-menu{margin-left:1px}.dropdown-submenu.dropleft .dropdown-menu{margin-right:1px}.navbar .dropdown-submenu .dropdown-menu,[x-placement^=bottom-] .dropdown-submenu .dropdown-menu{bottom:auto;margin-top:calc(-.5rem - 1px)}[x-placement^=top-] .dropdown-submenu .dropdown-menu{top:auto;bottom:0;margin-bottom:calc(-.5rem - 1px)}.dropdown-submenu.dropright>.dropdown-toggle{display:flex;justify-content:space-between;align-items:center}.dropdown-submenu.dropright>.dropdown-toggle::after{margin-right:-12px} +/*# sourceMappingURL=bootstrap-submenu.min.css.map */ \ No newline at end of file diff --git a/dist/css/bootstrap-submenu.min.css.map b/dist/css/bootstrap-submenu.min.css.map new file mode 100644 index 0000000..6253fc3 --- /dev/null +++ b/dist/css/bootstrap-submenu.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["dist/css/bootstrap-submenu.css"],"names":[],"mappings":"AAAA,2CACE,YAAa,IAGf,0CACE,aAAc,IAIhB,yCADA,wDAEE,OAAQ,KACR,WAAY,mBAGd,qDACE,IAAK,KACL,OAAQ,EACR,cAAe,mBAGjB,6CACE,QAAS,KACT,gBAAiB,cACjB,YAAa,OAGf,oDACE,aAAc","sourcesContent":[".dropdown-submenu.dropright .dropdown-menu {\n margin-left: 1px;\n}\n\n.dropdown-submenu.dropleft .dropdown-menu {\n margin-right: 1px;\n}\n\n[x-placement^=\"bottom-\"] .dropdown-submenu .dropdown-menu,\n.navbar .dropdown-submenu .dropdown-menu {\n bottom: auto;\n margin-top: calc(-0.5rem - 1px);\n}\n\n[x-placement^=\"top-\"] .dropdown-submenu .dropdown-menu {\n top: auto;\n bottom: 0;\n margin-bottom: calc(-0.5rem - 1px);\n}\n\n.dropdown-submenu.dropright > .dropdown-toggle {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.dropdown-submenu.dropright > .dropdown-toggle::after {\n margin-right: -12px;\n}\n"]} \ No newline at end of file diff --git a/dist/js/bootstrap-submenu.js b/dist/js/bootstrap-submenu.js index 96dafd3..8218169 100644 --- a/dist/js/bootstrap-submenu.js +++ b/dist/js/bootstrap-submenu.js @@ -1,17 +1,4 @@ -/*! - * Bootstrap-submenu v2.0.4 (https://vsn4ik.github.io/bootstrap-submenu/) - * Copyright 2014-2018 Vasilii A. (https://github.com/vsn4ik) - * Licensed under the MIT license - */ - -/** - * $.inArray: friends with IE8. Use Array.prototype.indexOf in future. - * $.proxy: friends with IE8. Use Function.prototype.bind in future. - */ - -'use strict'; - -(function(factory) { +(function (factory) { if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module define(['jquery'], factory); @@ -22,172 +9,144 @@ // Browser globals factory(jQuery); } -})(function($) { - function Item(element) { - this.$element = $(element); - this.$menu = this.$element.closest('.dropdown-menu'); - this.$main = this.$menu.parent(); - this.$items = this.$menu.children('.dropdown-submenu'); - - this.init(); - } - - Item.prototype = { - init: function() { - this.$element.on('keydown', $.proxy(this, 'keydown')); - }, - close: function() { - this.$main.removeClass('open'); - this.$items.trigger('hide.bs.submenu'); - }, - keydown: function(event) { - // 27: Esc - - if (event.keyCode == 27) { - event.stopPropagation(); - - this.close(); - this.$main.children('a, button').trigger('focus'); - } +})(function ($) { + var DropdownSubmenu = + /*#__PURE__*/ + function () { + function DropdownSubmenu(element) { + this.element = element.parentElement; + this.menuElement = this.element.querySelector('.dropdown-menu'); + this.init(); } - }; - function SubmenuItem(element) { - this.$element = $(element); - this.$main = this.$element.parent(); - this.$menu = this.$main.children('.dropdown-menu'); - this.$subs = this.$main.siblings('.dropdown-submenu'); - this.$items = this.$menu.children('.dropdown-submenu'); + var _proto = DropdownSubmenu.prototype; - this.init(); - } + _proto.init = function init() { + var _this = this; - $.extend(SubmenuItem.prototype, Item.prototype, { - init: function() { - this.$element.on({ - click: $.proxy(this, 'click'), - keydown: $.proxy(this, 'keydown') - }); + $(this.element).off('keydown.bs.dropdown.data-api'); + this.menuElement.addEventListener('keydown', this.itemKeydown.bind(this)); + var dropdownItemNodeList = this.menuElement.querySelectorAll('.dropdown-item'); - this.$main.on('hide.bs.submenu', $.proxy(this, 'hide')); - }, - click: function(event) { - // Fix a[href="#"]. For community - event.preventDefault(); + for (var _iterator = dropdownItemNodeList, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { + var _ref; - event.stopPropagation(); - - this.toggle(); - }, - hide: function(event) { - // Stop event bubbling - event.stopPropagation(); + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } - this.close(); - }, - open: function() { - this.$main.addClass('open'); - this.$subs.trigger('hide.bs.submenu'); - }, - toggle: function() { - if (this.$main.hasClass('open')) { - this.close(); - } - else { - this.open(); + var element = _ref; + element.addEventListener('keydown', this.handleKeydownDropdownItem.bind(this)); } - }, - keydown: function(event) { - // 13: Return, 32: Spacebar - if (event.keyCode == 32) { - // Off vertical scrolling - event.preventDefault(); - } + $(this.menuElement).on('keydown', '.dropdown-submenu > .dropdown-item', this.handleKeydownSubmenuDropdownItem.bind(this)); + $(this.menuElement).on('click', '.dropdown-submenu > .dropdown-item', this.handleClickSubmenuDropdownItem.bind(this)); + $(this.element).on('hidden.bs.dropdown', function () { + _this.close(_this.menuElement); + }); + }; - if ($.inArray(event.keyCode, [13, 32]) != -1) { - this.toggle(); + _proto.handleKeydownDropdownItem = function handleKeydownDropdownItem(event) { + // 27: Esc + if (event.keyCode !== 27) { + return; } - } - }); - function Submenupicker(element) { - this.$element = $(element); - this.$main = this.$element.parent(); - this.$menu = this.$main.children('.dropdown-menu'); - this.$items = this.$menu.children('.dropdown-submenu'); + event.target.closest('.dropdown-menu').previousElementSibling.focus(); + event.target.closest('.dropdown-menu').classList.remove('show'); + }; - this.init(); - } + _proto.handleKeydownSubmenuDropdownItem = function handleKeydownSubmenuDropdownItem(event) { + // 32: Spacebar + if (event.keyCode !== 32) { + return; + } // NOTE: Off vertical scrolling - Submenupicker.prototype = { - init: function() { - this.$menu.off('keydown.bs.dropdown.data-api'); - this.$menu.on('keydown', $.proxy(this, 'itemKeydown')); - this.$menu.find('li > a').each(function() { - new Item(this); - }); + event.preventDefault(); + this.toggle(event.target); + }; - this.$menu.find('.dropdown-submenu > a').each(function() { - new SubmenuItem(this); - }); + _proto.handleClickSubmenuDropdownItem = function handleClickSubmenuDropdownItem(event) { + event.stopPropagation(); + this.toggle(event.target); + }; - this.$main.on('hidden.bs.dropdown', $.proxy(this, 'hidden')); - }, - hidden: function() { - this.$items.trigger('hide.bs.submenu'); - }, - itemKeydown: function(event) { + _proto.itemKeydown = function itemKeydown(event) { // 38: Arrow up, 40: Arrow down + if (![38, 40].includes(event.keyCode)) { + return; + } // NOTE: Off vertical scrolling - if ($.inArray(event.keyCode, [38, 40]) != -1) { - // Off vertical scrolling - event.preventDefault(); - event.stopPropagation(); + event.preventDefault(); + event.stopPropagation(); + var itemNodeList = this.element.querySelectorAll('.show > .dropdown-item:not(:disabled):not(.disabled), .show > .dropdown > .dropdown-item'); + var index = Array.from(itemNodeList).findIndex(function (element) { + return element === event.target; + }); - var $items = this.$menu.find('li:not(.disabled):visible > a'); - var index = $items.index(event.target); + if (event.keyCode === 38 && index !== 0) { + index--; + } else if (event.keyCode === 40 && index !== itemNodeList.length - 1) { + index++; + } else { + return; + } - if (event.keyCode == 38 && index !== 0) { - index--; - } - else if (event.keyCode == 40 && index !== $items.length - 1) { - index++; - } - else { - return; + itemNodeList[index].focus(); + }; + + _proto.toggle = function toggle(element) { + var dropdownElement = element.closest('.dropdown'); + var parentMenuElement = dropdownElement.closest('.dropdown-menu'); + var menuElement = dropdownElement.querySelector('.dropdown-menu'); + var isOpen = menuElement.classList.contains('show'); + this.close(parentMenuElement); + menuElement.classList.toggle('show', !isOpen); + }; + + _proto.close = function close(menuElement) { + var menuNodeList = menuElement.querySelectorAll('.dropdown-menu.show'); + + for (var _iterator2 = menuNodeList, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; } - $items.eq(index).trigger('focus'); + var element = _ref2; + element.classList.remove('show'); } - } - }; + }; - var old = $.fn.submenupicker; - - // For AMD/Node/CommonJS used elements (optional) + return DropdownSubmenu; + }(); // For AMD/Node/CommonJS used elements (optional) // http://learn.jquery.com/jquery-ui/environments/amd/ - $.fn.submenupicker = function(elements) { - var $elements = this instanceof $ ? this : $(elements); - return $elements.each(function() { + + $.fn.submenupicker = function (elements) { + var $elements = this instanceof $ ? this : $(elements); + return $elements.each(function () { var data = $.data(this, 'bs.submenu'); if (!data) { - data = new Submenupicker(this); - + data = new DropdownSubmenu(this); $.data(this, 'bs.submenu', data); } }); }; - $.fn.submenupicker.Constructor = Submenupicker; - $.fn.submenupicker.noConflict = function() { - $.fn.submenupicker = old; - return this; - }; - - return $.fn.submenupicker; -}); + return DropdownSubmenu; +}); \ No newline at end of file diff --git a/dist/js/bootstrap-submenu.min.js b/dist/js/bootstrap-submenu.min.js index 57ade72..84178e1 100644 --- a/dist/js/bootstrap-submenu.min.js +++ b/dist/js/bootstrap-submenu.min.js @@ -1,7 +1 @@ -/*! - * Bootstrap-submenu v2.0.4 (https://vsn4ik.github.io/bootstrap-submenu/) - * Copyright 2014-2018 Vasilii A. (https://github.com/vsn4ik) - * Licensed under the MIT license - */ - -"use strict";!function(n){"function"==typeof define&&define.amd?define(["jquery"],n):"object"==typeof exports?module.exports=n(require("jquery")):n(jQuery)}(function(n){function e(e){this.$element=n(e),this.$menu=this.$element.closest(".dropdown-menu"),this.$main=this.$menu.parent(),this.$items=this.$menu.children(".dropdown-submenu"),this.init()}function i(e){this.$element=n(e),this.$main=this.$element.parent(),this.$menu=this.$main.children(".dropdown-menu"),this.$subs=this.$main.siblings(".dropdown-submenu"),this.$items=this.$menu.children(".dropdown-submenu"),this.init()}function t(e){this.$element=n(e),this.$main=this.$element.parent(),this.$menu=this.$main.children(".dropdown-menu"),this.$items=this.$menu.children(".dropdown-submenu"),this.init()}e.prototype={init:function(){this.$element.on("keydown",n.proxy(this,"keydown"))},close:function(){this.$main.removeClass("open"),this.$items.trigger("hide.bs.submenu")},keydown:function(n){27==n.keyCode&&(n.stopPropagation(),this.close(),this.$main.children("a, button").trigger("focus"))}},n.extend(i.prototype,e.prototype,{init:function(){this.$element.on({click:n.proxy(this,"click"),keydown:n.proxy(this,"keydown")}),this.$main.on("hide.bs.submenu",n.proxy(this,"hide"))},click:function(n){n.preventDefault(),n.stopPropagation(),this.toggle()},hide:function(n){n.stopPropagation(),this.close()},open:function(){this.$main.addClass("open"),this.$subs.trigger("hide.bs.submenu")},toggle:function(){this.$main.hasClass("open")?this.close():this.open()},keydown:function(e){32==e.keyCode&&e.preventDefault(),-1!=n.inArray(e.keyCode,[13,32])&&this.toggle()}}),t.prototype={init:function(){this.$menu.off("keydown.bs.dropdown.data-api"),this.$menu.on("keydown",n.proxy(this,"itemKeydown")),this.$menu.find("li > a").each(function(){new e(this)}),this.$menu.find(".dropdown-submenu > a").each(function(){new i(this)}),this.$main.on("hidden.bs.dropdown",n.proxy(this,"hidden"))},hidden:function(){this.$items.trigger("hide.bs.submenu")},itemKeydown:function(e){if(-1!=n.inArray(e.keyCode,[38,40])){e.preventDefault(),e.stopPropagation();var i=this.$menu.find("li:not(.disabled):visible > a"),t=i.index(e.target);if(38==e.keyCode&&0!==t)t--;else{if(40!=e.keyCode||t===i.length-1)return;t++}i.eq(t).trigger("focus")}}};var s=n.fn.submenupicker;return n.fn.submenupicker=function(e){return(this instanceof n?this:n(e)).each(function(){var e=n.data(this,"bs.submenu");e||(e=new t(this),n.data(this,"bs.submenu",e))})},n.fn.submenupicker.Constructor=t,n.fn.submenupicker.noConflict=function(){return n.fn.submenupicker=s,this},n.fn.submenupicker}); \ No newline at end of file +!function(factory){"function"==typeof define&&define.amd?define(["jquery"],factory):"object"==typeof exports?module.exports=factory(require("jquery")):factory(jQuery)}(function($){var DropdownSubmenu=function(){function DropdownSubmenu(element){this.element=element.parentElement,this.menuElement=this.element.querySelector(".dropdown-menu"),this.init()}var _proto=DropdownSubmenu.prototype;return _proto.init=function(){var _this=this;$(this.element).off("keydown.bs.dropdown.data-api"),this.menuElement.addEventListener("keydown",this.itemKeydown.bind(this));var _iterator=this.menuElement.querySelectorAll(".dropdown-item"),_isArray=Array.isArray(_iterator),_i=0;for(_iterator=_isArray?_iterator:_iterator[Symbol.iterator]();;){var _ref;if(_isArray){if(_i>=_iterator.length)break;_ref=_iterator[_i++]}else{if((_i=_iterator.next()).done)break;_ref=_i.value}_ref.addEventListener("keydown",this.handleKeydownDropdownItem.bind(this))}$(this.menuElement).on("keydown",".dropdown-submenu > .dropdown-item",this.handleKeydownSubmenuDropdownItem.bind(this)),$(this.menuElement).on("click",".dropdown-submenu > .dropdown-item",this.handleClickSubmenuDropdownItem.bind(this)),$(this.element).on("hidden.bs.dropdown",function(){_this.close(_this.menuElement)})},_proto.handleKeydownDropdownItem=function(event){27===event.keyCode&&(event.target.closest(".dropdown-menu").previousElementSibling.focus(),event.target.closest(".dropdown-menu").classList.remove("show"))},_proto.handleKeydownSubmenuDropdownItem=function(event){32===event.keyCode&&(event.preventDefault(),this.toggle(event.target))},_proto.handleClickSubmenuDropdownItem=function(event){event.stopPropagation(),this.toggle(event.target)},_proto.itemKeydown=function(event){if([38,40].includes(event.keyCode)){event.preventDefault(),event.stopPropagation();var itemNodeList=this.element.querySelectorAll(".show > .dropdown-item:not(:disabled):not(.disabled), .show > .dropdown > .dropdown-item"),index=Array.from(itemNodeList).findIndex(function(element){return element===event.target});if(38===event.keyCode&&0!==index)index--;else{if(40!==event.keyCode||index===itemNodeList.length-1)return;index++}itemNodeList[index].focus()}},_proto.toggle=function(element){var dropdownElement=element.closest(".dropdown"),parentMenuElement=dropdownElement.closest(".dropdown-menu"),menuElement=dropdownElement.querySelector(".dropdown-menu"),isOpen=menuElement.classList.contains("show");this.close(parentMenuElement),menuElement.classList.toggle("show",!isOpen)},_proto.close=function(menuElement){var _iterator2=menuElement.querySelectorAll(".dropdown-menu.show"),_isArray2=Array.isArray(_iterator2),_i2=0;for(_iterator2=_isArray2?_iterator2:_iterator2[Symbol.iterator]();;){var _ref2;if(_isArray2){if(_i2>=_iterator2.length)break;_ref2=_iterator2[_i2++]}else{if((_i2=_iterator2.next()).done)break;_ref2=_i2.value}_ref2.classList.remove("show")}},DropdownSubmenu}();return $.fn.submenupicker=function(elements){return(this instanceof $?this:$(elements)).each(function(){var data=$.data(this,"bs.submenu");data||(data=new DropdownSubmenu(this),$.data(this,"bs.submenu",data))})},DropdownSubmenu}); \ No newline at end of file diff --git a/docs/_config.yaml b/docs/_config.yaml new file mode 100644 index 0000000..c618b59 --- /dev/null +++ b/docs/_config.yaml @@ -0,0 +1,28 @@ +# Dependencies +# $ gem install rouge +# $ rougify style base16.solarized > assets/css/highlighter.css +highlighter: rouge + +# Custom variables +repository: "https://github.com/vsn4ik/bootstrap-submenu" +version: 3.0.0 +name: "Bootstrap-submenu" +description: "Bootstrap Sub-Menus" +keywords: "bootstrap dropdown jquery-plugin submenu" + +author: + name: "Vasilii A." + +cdn: + bootstrap: + css: "https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.css" + js: "https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.js" + + jquery: + js: "https://code.jquery.com/jquery-3.3.1.js" + + popper: + js: "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.js" + + fa: + css: "https://use.fontawesome.com/releases/v5.0.9/css/all.css" diff --git a/docs/_includes/dropdown-menu-elements.html b/docs/_includes/dropdown-menu-elements.html new file mode 100644 index 0000000..fc6f280 --- /dev/null +++ b/docs/_includes/dropdown-menu-elements.html @@ -0,0 +1,46 @@ + + + + + + + + + diff --git a/docs/_includes/footer.html b/docs/_includes/footer.html new file mode 100644 index 0000000..12c89d0 --- /dev/null +++ b/docs/_includes/footer.html @@ -0,0 +1,3 @@ +
+ © {{ site.author.name }}, 2014–{{ site.time | date: '%Y' }} +
diff --git a/docs/_includes/head.html b/docs/_includes/head.html new file mode 100644 index 0000000..850daf3 --- /dev/null +++ b/docs/_includes/head.html @@ -0,0 +1,24 @@ + + + + + + + + + + + +{{ site.name }} + + + + + + + + + + + + diff --git a/docs/_includes/header.html b/docs/_includes/header.html new file mode 100644 index 0000000..9c26298 --- /dev/null +++ b/docs/_includes/header.html @@ -0,0 +1,16 @@ +
+

{{ site.name }}

+

{{ site.description }}.

+ + +
diff --git a/docs/_includes/section-example-dropdown.html b/docs/_includes/section-example-dropdown.html new file mode 100644 index 0000000..591af22 --- /dev/null +++ b/docs/_includes/section-example-dropdown.html @@ -0,0 +1,53 @@ +

Dropdown

+ +

With button

+
+
+ +
+ +
+ +
+
+ +

With button-group

+
+
+
+ + + + +
+
+ +
+
+ + + + +
+
+
diff --git a/docs/_includes/section-example-dropup.html b/docs/_includes/section-example-dropup.html new file mode 100644 index 0000000..708c9b2 --- /dev/null +++ b/docs/_includes/section-example-dropup.html @@ -0,0 +1,53 @@ +

Dropup

+ +

With button

+
+
+
+ + + +
+
+ +
+
+ + + +
+
+
+ +

With button-group

+
+
+
+ + + + +
+
+ +
+
+ + + + +
+
+
diff --git a/docs/_includes/section-example-navbar.html b/docs/_includes/section-example-navbar.html new file mode 100644 index 0000000..d9c4067 --- /dev/null +++ b/docs/_includes/section-example-navbar.html @@ -0,0 +1,45 @@ +

Navbar

+ + diff --git a/docs/_includes/section-example-pills.html b/docs/_includes/section-example-pills.html new file mode 100644 index 0000000..0e5e91f --- /dev/null +++ b/docs/_includes/section-example-pills.html @@ -0,0 +1,37 @@ +

Pills

+ + diff --git a/docs/_includes/section-installation.html b/docs/_includes/section-installation.html new file mode 100644 index 0000000..1b97a30 --- /dev/null +++ b/docs/_includes/section-installation.html @@ -0,0 +1,27 @@ +
+{% highlight html %} + + + + … + + + … + + + + … + + +{% endhighlight %} +
+ +

Enable Bootstrap-submenu via JavaScript:

+ +
+{% highlight js %} +// For v2 [data-toggle="dropdown"] is required for [data-submenu]. +// For v2 .dropdown-submenu > [data-toggle="dropdown"] is forbidden. +$('[data-submenu]').submenupicker(); +{%- endhighlight %} +
diff --git a/docs/assets/css/docs.css b/docs/assets/css/docs.css index b1675a1..718b629 100644 --- a/docs/assets/css/docs.css +++ b/docs/assets/css/docs.css @@ -1,30 +1,15 @@ -body { - padding-top: 20px; -} -footer { - padding-bottom: 10px; -} -a { - cursor: pointer; -} -.m-b { - margin-bottom: 15px; -} -.input-group-addon, -.input-group-btn { - width: auto; -} -.input-group-addon { - background-color: white; -} -pre { - padding: 0; -} -.dropdown-menu .disabled, -.dropdown-menu .dropdown-header, -.dropdown-menu .divider { +.highlight, +.highlight pre { + margin-bottom: 0; +} + +.dropdown-item:disabled, +.dropdown-item.disabled, +.dropdown-header, +.dropdown-divider { pointer-events: none; } + /* Без враппера происходит подергивание */ .scroll-top-wrapper { position: fixed; @@ -33,19 +18,22 @@ pre { opacity: 0.7; transition: opacity 0.15s ease-in-out; } + .scroll-top-wrapper:hover { opacity: 1; } + ::-webkit-scrollbar { width: 10px; height: 10px; -} + ::-webkit-scrollbar-track { background-color: rgba(113, 112, 107, 0.1); } + ::-webkit-scrollbar-thumb { background-color: rgba(0, 0, 0, 0.2); -} + ::-webkit-scrollbar-thumb:hover { background-color: gray; } diff --git a/docs/assets/css/highlighter.css b/docs/assets/css/highlighter.css new file mode 100644 index 0000000..009bb21 --- /dev/null +++ b/docs/assets/css/highlighter.css @@ -0,0 +1,77 @@ +.highlight table td { padding: 5px; } +.highlight table pre { margin: 0; } +.highlight, .highlight .w { + color: #586e75; +} +.highlight .err { + color: #002b36; + background-color: #dc322f; +} +.highlight .c, .highlight .cd, .highlight .cm, .highlight .c1, .highlight .cs { + color: #657b83; +} +.highlight .cp { + color: #b58900; +} +.highlight .nt { + color: #b58900; +} +.highlight .o, .highlight .ow { + color: #93a1a1; +} +.highlight .p, .highlight .pi { + color: #93a1a1; +} +.highlight .gi { + color: #859900; +} +.highlight .gd { + color: #dc322f; +} +.highlight .gh { + color: #268bd2; + background-color: #002b36; + font-weight: bold; +} +.highlight .k, .highlight .kn, .highlight .kp, .highlight .kr, .highlight .kv { + color: #6c71c4; +} +.highlight .kc { + color: #cb4b16; +} +.highlight .kt { + color: #cb4b16; +} +.highlight .kd { + color: #cb4b16; +} +.highlight .s, .highlight .sb, .highlight .sc, .highlight .sd, .highlight .s2, .highlight .sh, .highlight .sx, .highlight .s1 { + color: #859900; +} +.highlight .sr { + color: #2aa198; +} +.highlight .si { + color: #d33682; +} +.highlight .se { + color: #d33682; +} +.highlight .nn { + color: #b58900; +} +.highlight .nc { + color: #b58900; +} +.highlight .no { + color: #b58900; +} +.highlight .na { + color: #268bd2; +} +.highlight .m, .highlight .mf, .highlight .mh, .highlight .mi, .highlight .il, .highlight .mo, .highlight .mb, .highlight .mx { + color: #859900; +} +.highlight .ss { + color: #859900; +} diff --git a/docs/assets/js/docs.js b/docs/assets/js/docs.js index 9482fe6..2d76044 100644 --- a/docs/assets/js/docs.js +++ b/docs/assets/js/docs.js @@ -1,5 +1,3 @@ -// jscs:disable requireCamelCaseOrUpperCaseIdentifiers - 'use strict'; document.addEventListener('DOMContentLoaded', function() { @@ -13,11 +11,13 @@ document.addEventListener('DOMContentLoaded', function() { var html = '' + '
' + - '
' + - '
' + - '' + data.stargazers_count + '' + - ' ' + - '' + + '
' + + '
' + + '' + + data.stargazers_count + + ' ' + + '' + + '' + '
' + '
'; @@ -34,38 +34,43 @@ document.addEventListener('DOMContentLoaded', function() { document.documentElement ]; - var $scrollBtn = $('#scroll-top'); + var scrollButtonNode = document.querySelector('#scroll-top'); - function updateScrollBtnCls() { + function updateScrollButtonVisibility() { var scrollTop = containers.reduce(function(result, element) { return result + element.scrollTop; }, 0); - $scrollBtn.toggleClass('hidden', scrollTop < 100); + scrollButtonNode.classList.toggle('hidden', scrollTop < 100); } - $scrollBtn.on('click', function() { + scrollButtonNode.addEventListener('click', function() { window.onscroll = null; - $(this).addClass('hidden'); + scrollButtonNode.classList.add('hidden'); // 'html' for Mozilla Firefox, 'body' for other browsers $(containers).animate({ scrollTop: 0 }, 500, $.proxy(function() { - window.onscroll = updateScrollBtnCls; + window.onscroll = updateScrollButtonVisibility; }, this)); }); - window.onscroll = updateScrollBtnCls; + window.onscroll = updateScrollButtonVisibility; - // Dropdown fix - $('.dropdown > a[tabindex]').on('keydown', function(event) { - // 13: Return + // NOTE: Dropdown fix + $('a[tabindex][data-toggle="dropdown"]').on('keydown', function(event) { + // 13: Return, 32: Spacebar - if (event.keyCode === 13) { - $(this).dropdown('toggle'); + if (![13, 32].includes(event.keyCode)) { + return; } + + // NOTE: Off vertical scrolling + event.preventDefault(); + + $(this).dropdown('toggle'); }); // Для отмены закрытия при клике на неактивный элемент либо padding @@ -77,6 +82,5 @@ document.addEventListener('DOMContentLoaded', function() { $('[data-submenu]').submenupicker(); - updateScrollBtnCls(); - hljs.initHighlighting(); + updateScrollButtonVisibility(); }); diff --git a/docs/assets/less/docs.less b/docs/assets/less/docs.less deleted file mode 100644 index ea1c9f4..0000000 --- a/docs/assets/less/docs.less +++ /dev/null @@ -1,74 +0,0 @@ -// :: friends with IE8. Use :: in future. - -@import "bootstrap/less/mixins.less"; - -body { - padding-top: 20px; -} - -footer { - padding-bottom: 10px; -} - -a { - cursor: pointer; -} - -.m-b { - margin-bottom: 15px; -} - -.input-group-addon, -.input-group-btn { - width: auto; -} - -.input-group-addon { - background-color: white; -} - -pre { - padding: 0; -} - -.dropdown-menu { - // Убирать outline у .disabled теперь не требуется - .disabled, - .dropdown-header, - .divider { - // Элемент перестанет реагировать на hover, click и другие события мыши. - // Он станет «прозрачным» для взаимодействия, а hover и click - // будут передаваться элементу, лежащему под ним. - pointer-events: none; - } -} - -/* Без враппера происходит подергивание */ -.scroll-top-wrapper { - position: fixed; - right: 20px; - bottom: 20px; - opacity: 0.7; - - transition: opacity 0.15s ease-in-out; - - &:hover { - opacity: 1; - } -} - -::-webkit-scrollbar { - .square(10px); - - &-track { - background-color: rgba(113, 112, 107, 0.1); - } - - &-thumb { - background-color: rgba(0, 0, 0, 0.2); - - &:hover { - background-color: gray; - } - } -} diff --git a/docs/dist/css/bootstrap-submenu.css b/docs/dist/css/bootstrap-submenu.css new file mode 100644 index 0000000..8c76602 --- /dev/null +++ b/docs/dist/css/bootstrap-submenu.css @@ -0,0 +1,29 @@ +.dropdown-submenu.dropright .dropdown-menu { + margin-left: 1px; +} + +.dropdown-submenu.dropleft .dropdown-menu { + margin-right: 1px; +} + +[x-placement^="bottom-"] .dropdown-submenu .dropdown-menu, +.navbar .dropdown-submenu .dropdown-menu { + bottom: auto; + margin-top: calc(-0.5rem - 1px); +} + +[x-placement^="top-"] .dropdown-submenu .dropdown-menu { + top: auto; + bottom: 0; + margin-bottom: calc(-0.5rem - 1px); +} + +.dropdown-submenu.dropright > .dropdown-toggle { + display: flex; + justify-content: space-between; + align-items: center; +} + +.dropdown-submenu.dropright > .dropdown-toggle::after { + margin-right: -12px; +} diff --git a/docs/dist/css/bootstrap-submenu.min.css b/docs/dist/css/bootstrap-submenu.min.css new file mode 100644 index 0000000..5c635d6 --- /dev/null +++ b/docs/dist/css/bootstrap-submenu.min.css @@ -0,0 +1,2 @@ +.dropdown-submenu.dropright .dropdown-menu{margin-left:1px}.dropdown-submenu.dropleft .dropdown-menu{margin-right:1px}.navbar .dropdown-submenu .dropdown-menu,[x-placement^=bottom-] .dropdown-submenu .dropdown-menu{bottom:auto;margin-top:calc(-.5rem - 1px)}[x-placement^=top-] .dropdown-submenu .dropdown-menu{top:auto;bottom:0;margin-bottom:calc(-.5rem - 1px)}.dropdown-submenu.dropright>.dropdown-toggle{display:flex;justify-content:space-between;align-items:center}.dropdown-submenu.dropright>.dropdown-toggle::after{margin-right:-12px} +/*# sourceMappingURL=bootstrap-submenu.min.css.map */ \ No newline at end of file diff --git a/docs/dist/css/bootstrap-submenu.min.css.map b/docs/dist/css/bootstrap-submenu.min.css.map new file mode 100644 index 0000000..6253fc3 --- /dev/null +++ b/docs/dist/css/bootstrap-submenu.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["dist/css/bootstrap-submenu.css"],"names":[],"mappings":"AAAA,2CACE,YAAa,IAGf,0CACE,aAAc,IAIhB,yCADA,wDAEE,OAAQ,KACR,WAAY,mBAGd,qDACE,IAAK,KACL,OAAQ,EACR,cAAe,mBAGjB,6CACE,QAAS,KACT,gBAAiB,cACjB,YAAa,OAGf,oDACE,aAAc","sourcesContent":[".dropdown-submenu.dropright .dropdown-menu {\n margin-left: 1px;\n}\n\n.dropdown-submenu.dropleft .dropdown-menu {\n margin-right: 1px;\n}\n\n[x-placement^=\"bottom-\"] .dropdown-submenu .dropdown-menu,\n.navbar .dropdown-submenu .dropdown-menu {\n bottom: auto;\n margin-top: calc(-0.5rem - 1px);\n}\n\n[x-placement^=\"top-\"] .dropdown-submenu .dropdown-menu {\n top: auto;\n bottom: 0;\n margin-bottom: calc(-0.5rem - 1px);\n}\n\n.dropdown-submenu.dropright > .dropdown-toggle {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.dropdown-submenu.dropright > .dropdown-toggle::after {\n margin-right: -12px;\n}\n"]} \ No newline at end of file diff --git a/docs/dist/js/bootstrap-submenu.js b/docs/dist/js/bootstrap-submenu.js new file mode 100644 index 0000000..8218169 --- /dev/null +++ b/docs/dist/js/bootstrap-submenu.js @@ -0,0 +1,152 @@ +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module + define(['jquery'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + module.exports = factory(require('jquery')); + } else { + // Browser globals + factory(jQuery); + } +})(function ($) { + var DropdownSubmenu = + /*#__PURE__*/ + function () { + function DropdownSubmenu(element) { + this.element = element.parentElement; + this.menuElement = this.element.querySelector('.dropdown-menu'); + this.init(); + } + + var _proto = DropdownSubmenu.prototype; + + _proto.init = function init() { + var _this = this; + + $(this.element).off('keydown.bs.dropdown.data-api'); + this.menuElement.addEventListener('keydown', this.itemKeydown.bind(this)); + var dropdownItemNodeList = this.menuElement.querySelectorAll('.dropdown-item'); + + for (var _iterator = dropdownItemNodeList, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var element = _ref; + element.addEventListener('keydown', this.handleKeydownDropdownItem.bind(this)); + } + + $(this.menuElement).on('keydown', '.dropdown-submenu > .dropdown-item', this.handleKeydownSubmenuDropdownItem.bind(this)); + $(this.menuElement).on('click', '.dropdown-submenu > .dropdown-item', this.handleClickSubmenuDropdownItem.bind(this)); + $(this.element).on('hidden.bs.dropdown', function () { + _this.close(_this.menuElement); + }); + }; + + _proto.handleKeydownDropdownItem = function handleKeydownDropdownItem(event) { + // 27: Esc + if (event.keyCode !== 27) { + return; + } + + event.target.closest('.dropdown-menu').previousElementSibling.focus(); + event.target.closest('.dropdown-menu').classList.remove('show'); + }; + + _proto.handleKeydownSubmenuDropdownItem = function handleKeydownSubmenuDropdownItem(event) { + // 32: Spacebar + if (event.keyCode !== 32) { + return; + } // NOTE: Off vertical scrolling + + + event.preventDefault(); + this.toggle(event.target); + }; + + _proto.handleClickSubmenuDropdownItem = function handleClickSubmenuDropdownItem(event) { + event.stopPropagation(); + this.toggle(event.target); + }; + + _proto.itemKeydown = function itemKeydown(event) { + // 38: Arrow up, 40: Arrow down + if (![38, 40].includes(event.keyCode)) { + return; + } // NOTE: Off vertical scrolling + + + event.preventDefault(); + event.stopPropagation(); + var itemNodeList = this.element.querySelectorAll('.show > .dropdown-item:not(:disabled):not(.disabled), .show > .dropdown > .dropdown-item'); + var index = Array.from(itemNodeList).findIndex(function (element) { + return element === event.target; + }); + + if (event.keyCode === 38 && index !== 0) { + index--; + } else if (event.keyCode === 40 && index !== itemNodeList.length - 1) { + index++; + } else { + return; + } + + itemNodeList[index].focus(); + }; + + _proto.toggle = function toggle(element) { + var dropdownElement = element.closest('.dropdown'); + var parentMenuElement = dropdownElement.closest('.dropdown-menu'); + var menuElement = dropdownElement.querySelector('.dropdown-menu'); + var isOpen = menuElement.classList.contains('show'); + this.close(parentMenuElement); + menuElement.classList.toggle('show', !isOpen); + }; + + _proto.close = function close(menuElement) { + var menuNodeList = menuElement.querySelectorAll('.dropdown-menu.show'); + + for (var _iterator2 = menuNodeList, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var element = _ref2; + element.classList.remove('show'); + } + }; + + return DropdownSubmenu; + }(); // For AMD/Node/CommonJS used elements (optional) + // http://learn.jquery.com/jquery-ui/environments/amd/ + + + $.fn.submenupicker = function (elements) { + var $elements = this instanceof $ ? this : $(elements); + return $elements.each(function () { + var data = $.data(this, 'bs.submenu'); + + if (!data) { + data = new DropdownSubmenu(this); + $.data(this, 'bs.submenu', data); + } + }); + }; + + return DropdownSubmenu; +}); \ No newline at end of file diff --git a/docs/dist/js/bootstrap-submenu.min.js b/docs/dist/js/bootstrap-submenu.min.js new file mode 100644 index 0000000..84178e1 --- /dev/null +++ b/docs/dist/js/bootstrap-submenu.min.js @@ -0,0 +1 @@ +!function(factory){"function"==typeof define&&define.amd?define(["jquery"],factory):"object"==typeof exports?module.exports=factory(require("jquery")):factory(jQuery)}(function($){var DropdownSubmenu=function(){function DropdownSubmenu(element){this.element=element.parentElement,this.menuElement=this.element.querySelector(".dropdown-menu"),this.init()}var _proto=DropdownSubmenu.prototype;return _proto.init=function(){var _this=this;$(this.element).off("keydown.bs.dropdown.data-api"),this.menuElement.addEventListener("keydown",this.itemKeydown.bind(this));var _iterator=this.menuElement.querySelectorAll(".dropdown-item"),_isArray=Array.isArray(_iterator),_i=0;for(_iterator=_isArray?_iterator:_iterator[Symbol.iterator]();;){var _ref;if(_isArray){if(_i>=_iterator.length)break;_ref=_iterator[_i++]}else{if((_i=_iterator.next()).done)break;_ref=_i.value}_ref.addEventListener("keydown",this.handleKeydownDropdownItem.bind(this))}$(this.menuElement).on("keydown",".dropdown-submenu > .dropdown-item",this.handleKeydownSubmenuDropdownItem.bind(this)),$(this.menuElement).on("click",".dropdown-submenu > .dropdown-item",this.handleClickSubmenuDropdownItem.bind(this)),$(this.element).on("hidden.bs.dropdown",function(){_this.close(_this.menuElement)})},_proto.handleKeydownDropdownItem=function(event){27===event.keyCode&&(event.target.closest(".dropdown-menu").previousElementSibling.focus(),event.target.closest(".dropdown-menu").classList.remove("show"))},_proto.handleKeydownSubmenuDropdownItem=function(event){32===event.keyCode&&(event.preventDefault(),this.toggle(event.target))},_proto.handleClickSubmenuDropdownItem=function(event){event.stopPropagation(),this.toggle(event.target)},_proto.itemKeydown=function(event){if([38,40].includes(event.keyCode)){event.preventDefault(),event.stopPropagation();var itemNodeList=this.element.querySelectorAll(".show > .dropdown-item:not(:disabled):not(.disabled), .show > .dropdown > .dropdown-item"),index=Array.from(itemNodeList).findIndex(function(element){return element===event.target});if(38===event.keyCode&&0!==index)index--;else{if(40!==event.keyCode||index===itemNodeList.length-1)return;index++}itemNodeList[index].focus()}},_proto.toggle=function(element){var dropdownElement=element.closest(".dropdown"),parentMenuElement=dropdownElement.closest(".dropdown-menu"),menuElement=dropdownElement.querySelector(".dropdown-menu"),isOpen=menuElement.classList.contains("show");this.close(parentMenuElement),menuElement.classList.toggle("show",!isOpen)},_proto.close=function(menuElement){var _iterator2=menuElement.querySelectorAll(".dropdown-menu.show"),_isArray2=Array.isArray(_iterator2),_i2=0;for(_iterator2=_isArray2?_iterator2:_iterator2[Symbol.iterator]();;){var _ref2;if(_isArray2){if(_i2>=_iterator2.length)break;_ref2=_iterator2[_i2++]}else{if((_i2=_iterator2.next()).done)break;_ref2=_i2.value}_ref2.classList.remove("show")}},DropdownSubmenu}();return $.fn.submenupicker=function(elements){return(this instanceof $?this:$(elements)).each(function(){var data=$.data(this,"bs.submenu");data||(data=new DropdownSubmenu(this),$.data(this,"bs.submenu",data))})},DropdownSubmenu}); \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index 56e7b1e..07d84ed 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,23 +1,34 @@ +--- +--- + -<%- include views/head -%> + + + {% include head.html %} + -
- <%- include views/header -%> +
+ {% include header.html %} - <%- include views/section_installation -%> +

Installation

+ {% include section-installation.html %}
- <%- include views/section_html_examples -%> +

Examples

+ {% include section-example-dropdown.html %} + {% include section-example-dropup.html %} + {% include section-example-navbar.html %} + {% include section-example-pills.html %}
- <%- include views/footer -%> + {% include footer.html %}
diff --git a/docs/views/dropdown-menu-elements.html b/docs/views/dropdown-menu-elements.html deleted file mode 100644 index 52ad82b..0000000 --- a/docs/views/dropdown-menu-elements.html +++ /dev/null @@ -1,40 +0,0 @@ - - - -
  • Something else here
  • -
  • -
  • Separated link
  • diff --git a/docs/views/dropdown-menu-right.html b/docs/views/dropdown-menu-right.html deleted file mode 100644 index 861b1bd..0000000 --- a/docs/views/dropdown-menu-right.html +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/docs/views/dropdown-menu.html b/docs/views/dropdown-menu.html deleted file mode 100644 index fda2772..0000000 --- a/docs/views/dropdown-menu.html +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/docs/views/footer.ejs b/docs/views/footer.ejs deleted file mode 100644 index 3eb9ec6..0000000 --- a/docs/views/footer.ejs +++ /dev/null @@ -1,4 +0,0 @@ - -
    -

    © <%= pkg.author.name %>, 2014–<%= year %>

    -
    diff --git a/docs/views/head.ejs b/docs/views/head.ejs deleted file mode 100644 index 3333572..0000000 --- a/docs/views/head.ejs +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - <%= pkg.name[0].toUpperCase() + pkg.name.slice(1) %> - - - - - - - - - - - - - - diff --git a/docs/views/header.ejs b/docs/views/header.ejs deleted file mode 100644 index a62c4c4..0000000 --- a/docs/views/header.ejs +++ /dev/null @@ -1,16 +0,0 @@ -
    -

    <%= pkg.name.charAt(0).toUpperCase() + pkg.name.slice(1) %>

    -

    <%= pkg.description %>.

    - - -
    diff --git a/docs/views/section_html_examples.ejs b/docs/views/section_html_examples.ejs deleted file mode 100644 index 1227aa6..0000000 --- a/docs/views/section_html_examples.ejs +++ /dev/null @@ -1,170 +0,0 @@ -

    Examples

    - -

    Dropdown

    - -

    With button

    -
    -
    - -
    - -
    - -
    -
    - -

    With button-group

    -
    -
    -
    - - - - <%- include dropdown-menu.html -%> -
    -
    - -
    -
    - - - - <%- include dropdown-menu-right.html -%> -
    -
    -
    - -

    Dropup

    - -

    With button

    -
    -
    -
    - - - <%- include dropdown-menu.html -%> -
    -
    - -
    -
    - - - <%- include dropdown-menu-right.html -%> -
    -
    -
    - -

    With button-group

    -
    -
    -
    - - - - <%- include dropdown-menu.html -%> -
    -
    - -
    -
    - - - - <%- include dropdown-menu-right.html -%> -
    -
    -
    - -

    Navbar

    - - -

    Pills

    - diff --git a/docs/views/section_installation.ejs b/docs/views/section_installation.ejs deleted file mode 100644 index cb0d111..0000000 --- a/docs/views/section_installation.ejs +++ /dev/null @@ -1,23 +0,0 @@ -

    Installation

    - -
    <!DOCTYPE html>
    -<html>
    -<head>
    -  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/<%= pkg.devDependencies.bootstrap.slice(1) %>/css/bootstrap.min.css">
    -  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/<%= pkg.devDependencies.bootstrap.slice(1) %>/css/bootstrap-theme.min.css">
    -  <link rel="stylesheet" href="dist/css/bootstrap-submenu.min.css">
    -
    -  <script src="https://code.jquery.com/jquery-<%= pkg.devDependencies.jquery.slice(1) %>.min.js" defer></script>
    -  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/<%= pkg.devDependencies.bootstrap.slice(1) %>/js/bootstrap.min.js" defer></script>
    -  <script src="dist/js/bootstrap-submenu.min.js" defer></script>
    -</head>
    -<body>
    -  ...
    -</body>
    -</html>
    - -

    Enable Bootstrap-submenu via JavaScript:

    - -
    // For v2 [data-toggle="dropdown"] is required for [data-submenu].
    -// For v2 .dropdown-submenu > [data-toggle="dropdown"] is forbidden.
    -$('[data-submenu]').submenupicker();
    diff --git a/js/.jscsrc b/js/.jscsrc deleted file mode 100644 index 16584a4..0000000 --- a/js/.jscsrc +++ /dev/null @@ -1,43 +0,0 @@ -{ - "esnext": true, - "verbose": true, - "disallowEmptyBlocks": true, - "disallowKeywords": ["with"], - "disallowMixedSpacesAndTabs": true, - "disallowMultipleLineStrings": true, - "disallowMultipleVarDecl": true, - "disallowQuotedKeysInObjects": "allButReserved", - "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"], - "disallowSpaceBeforeBinaryOperators": [","], - "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"], - "disallowSpacesInFunctionDeclaration": { "beforeOpeningRoundBrace": true }, - "disallowSpacesInNamedFunctionExpression": { "beforeOpeningRoundBrace": true }, - "disallowSpacesInsideArrayBrackets": true, - "disallowSpacesInsideParentheses": true, - "disallowTrailingComma": true, - "disallowTrailingWhitespace": true, - "requireCamelCaseOrUpperCaseIdentifiers": true, - "requireCapitalizedConstructors": true, - "requireCommaBeforeLineBreak": true, - "requireDollarBeforejQueryAssignment": true, - "requireDotNotation": true, - "requireLineFeedAtFileEnd": true, - "requirePaddingNewLinesAfterUseStrict": true, - "requirePaddingNewLinesBeforeExport": true, - "requireSpaceAfterBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", "<", ">=", "<="], - "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"], - "requireSpaceAfterLineComment": true, - "requireSpaceBeforeBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", "<", ">=", "<="], - "requireSpaceBetweenArguments": true, - "requireSpacesInAnonymousFunctionExpression": { "beforeOpeningCurlyBrace": true, "allExcept": ["shorthand"] }, - "requireSpacesInConditionalExpression": true, - "requireSpacesInForStatement": true, - "requireSpacesInFunctionDeclaration": { "beforeOpeningCurlyBrace": true }, - "requireSpacesInFunctionExpression": { "beforeOpeningCurlyBrace": true }, - "requireSpacesInNamedFunctionExpression": { "beforeOpeningCurlyBrace": true }, - "requireSpacesInsideObjectBrackets": "allButNested", - "validateAlignedFunctionParameters": true, - "validateIndentation": 2, - "validateLineBreaks": "LF", - "validateQuoteMarks": "'" -} diff --git a/js/bootstrap-submenu.js b/js/bootstrap-submenu.js index e85525b..bee5883 100644 --- a/js/bootstrap-submenu.js +++ b/js/bootstrap-submenu.js @@ -1,10 +1,3 @@ -/** - * $.inArray: friends with IE8. Use Array.prototype.indexOf in future. - * $.proxy: friends with IE8. Use Function.prototype.bind in future. - */ - -'use strict'; - (function(factory) { if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module @@ -17,171 +10,123 @@ factory(jQuery); } })(function($) { - function Item(element) { - this.$element = $(element); - this.$menu = this.$element.closest('.dropdown-menu'); - this.$main = this.$menu.parent(); - this.$items = this.$menu.children('.dropdown-submenu'); + class DropdownSubmenu { + constructor(element) { + this.element = element.parentElement; + this.menuElement = this.element.querySelector('.dropdown-menu'); - this.init(); - } + this.init(); + } - Item.prototype = { - init: function() { - this.$element.on('keydown', $.proxy(this, 'keydown')); - }, - close: function() { - this.$main.removeClass('open'); - this.$items.trigger('hide.bs.submenu'); - }, - keydown: function(event) { - // 27: Esc + init() { + $(this.element).off('keydown.bs.dropdown.data-api'); - if (event.keyCode == 27) { - event.stopPropagation(); + this.menuElement.addEventListener('keydown', this.itemKeydown.bind(this)); - this.close(); - this.$main.children('a, button').trigger('focus'); + const dropdownItemNodeList = this.menuElement.querySelectorAll('.dropdown-item'); + + for (const element of dropdownItemNodeList) { + element.addEventListener('keydown', this.handleKeydownDropdownItem.bind(this)); } + + $(this.menuElement).on('keydown', '.dropdown-submenu > .dropdown-item', this.handleKeydownSubmenuDropdownItem.bind(this)); + $(this.menuElement).on('click', '.dropdown-submenu > .dropdown-item', this.handleClickSubmenuDropdownItem.bind(this)); + $(this.element).on('hidden.bs.dropdown', () => { + this.close(this.menuElement); + }); } - }; - function SubmenuItem(element) { - this.$element = $(element); - this.$main = this.$element.parent(); - this.$menu = this.$main.children('.dropdown-menu'); - this.$subs = this.$main.siblings('.dropdown-submenu'); - this.$items = this.$menu.children('.dropdown-submenu'); + handleKeydownDropdownItem(event) { + // 27: Esc + if (event.keyCode !== 27) { + return; + } - this.init(); - } + event.target.closest('.dropdown-menu').previousElementSibling.focus(); + event.target.closest('.dropdown-menu').classList.remove('show'); + } - $.extend(SubmenuItem.prototype, Item.prototype, { - init: function() { - this.$element.on({ - click: $.proxy(this, 'click'), - keydown: $.proxy(this, 'keydown') - }); + handleKeydownSubmenuDropdownItem(event) { + // 32: Spacebar + if (event.keyCode !== 32) { + return; + } - this.$main.on('hide.bs.submenu', $.proxy(this, 'hide')); - }, - click: function(event) { - // Fix a[href="#"]. For community + // NOTE: Off vertical scrolling event.preventDefault(); - event.stopPropagation(); + this.toggle(event.target); + } - this.toggle(); - }, - hide: function(event) { - // Stop event bubbling + handleClickSubmenuDropdownItem(event) { event.stopPropagation(); - this.close(); - }, - open: function() { - this.$main.addClass('open'); - this.$subs.trigger('hide.bs.submenu'); - }, - toggle: function() { - if (this.$main.hasClass('open')) { - this.close(); - } - else { - this.open(); - } - }, - keydown: function(event) { - // 13: Return, 32: Spacebar - - if (event.keyCode == 32) { - // Off vertical scrolling - event.preventDefault(); - } + this.toggle(event.target); + } - if ($.inArray(event.keyCode, [13, 32]) != -1) { - this.toggle(); + itemKeydown(event) { + // 38: Arrow up, 40: Arrow down + if (![38, 40].includes(event.keyCode)) { + return; } - } - }); - function Submenupicker(element) { - this.$element = $(element); - this.$main = this.$element.parent(); - this.$menu = this.$main.children('.dropdown-menu'); - this.$items = this.$menu.children('.dropdown-submenu'); + // NOTE: Off vertical scrolling + event.preventDefault(); - this.init(); - } + event.stopPropagation(); - Submenupicker.prototype = { - init: function() { - this.$menu.off('keydown.bs.dropdown.data-api'); - this.$menu.on('keydown', $.proxy(this, 'itemKeydown')); + const itemNodeList = this.element.querySelectorAll('.show > .dropdown-item:not(:disabled):not(.disabled), .show > .dropdown > .dropdown-item'); - this.$menu.find('li > a').each(function() { - new Item(this); + let index = Array.from(itemNodeList).findIndex((element) => { + return element === event.target; }); - this.$menu.find('.dropdown-submenu > a').each(function() { - new SubmenuItem(this); - }); + if (event.keyCode === 38 && index !== 0) { + index--; + } else if (event.keyCode === 40 && index !== itemNodeList.length - 1) { + index++; + } else { + return; + } - this.$main.on('hidden.bs.dropdown', $.proxy(this, 'hidden')); - }, - hidden: function() { - this.$items.trigger('hide.bs.submenu'); - }, - itemKeydown: function(event) { - // 38: Arrow up, 40: Arrow down + itemNodeList[index].focus(); + } - if ($.inArray(event.keyCode, [38, 40]) != -1) { - // Off vertical scrolling - event.preventDefault(); + toggle(element) { + const dropdownElement = element.closest('.dropdown'); + const parentMenuElement = dropdownElement.closest('.dropdown-menu'); + const menuElement = dropdownElement.querySelector('.dropdown-menu'); + const isOpen = menuElement.classList.contains('show'); - event.stopPropagation(); + this.close(parentMenuElement); - var $items = this.$menu.find('li:not(.disabled):visible > a'); - var index = $items.index(event.target); + menuElement.classList.toggle('show', !isOpen); + } - if (event.keyCode == 38 && index !== 0) { - index--; - } - else if (event.keyCode == 40 && index !== $items.length - 1) { - index++; - } - else { - return; - } + close(menuElement) { + const menuNodeList = menuElement.querySelectorAll('.dropdown-menu.show'); - $items.eq(index).trigger('focus'); + for (const element of menuNodeList) { + element.classList.remove('show'); } } - }; - - var old = $.fn.submenupicker; + } // For AMD/Node/CommonJS used elements (optional) // http://learn.jquery.com/jquery-ui/environments/amd/ $.fn.submenupicker = function(elements) { - var $elements = this instanceof $ ? this : $(elements); + const $elements = this instanceof $ ? this : $(elements); return $elements.each(function() { - var data = $.data(this, 'bs.submenu'); + let data = $.data(this, 'bs.submenu'); if (!data) { - data = new Submenupicker(this); + data = new DropdownSubmenu(this); $.data(this, 'bs.submenu', data); } }); }; - $.fn.submenupicker.Constructor = Submenupicker; - $.fn.submenupicker.noConflict = function() { - $.fn.submenupicker = old; - return this; - }; - - return $.fn.submenupicker; + return DropdownSubmenu; }); diff --git a/less/bootstrap-submenu.less b/less/bootstrap-submenu.less deleted file mode 100644 index b955b3c..0000000 --- a/less/bootstrap-submenu.less +++ /dev/null @@ -1,102 +0,0 @@ -// :: friends with IE8. Use :: in future. - -@import "bootstrap/less/variables.less"; -@import "mixins.less"; - -// Variables -@caret-margin: -@caret-width-base * 2 - 2; - -// -// Sub-Menus -// -------------------------------------------------- - -.dropdown-submenu > a:after { - content: ""; -} - -@media (min-width: @grid-float-breakpoint) { - .dropdown-submenu { - position: relative; - - .dropdown-menu { - top: 0; - left: 100%; - margin-top: -6px; - border-top-left-radius: 0; - - // Strictly before .dropdown-menu-right - .dropup &, - .navbar-fixed-bottom & { - top: auto; - bottom: 0; - margin-top: 0; - margin-bottom: -6px; - border-top-left-radius: @border-radius-base; - border-bottom-left-radius: 0; - } - - .dropdown-menu-right &, - .navbar-right & { - left: auto; - right: 100%; - - border-top-left-radius: @border-radius-base; - border-top-right-radius: 0; - - .dropup &, - .navbar-fixed-bottom & { - border-radius: @border-radius-base @border-radius-base 0; - } - } - } - - > a:after { - float: right; - margin-top: @line-height-computed / 2 - @caret-width-base; - margin-right: @caret-margin; - - .make-caret(left, top, bottom); - - .dropdown-menu-right &, - .navbar-right & { - float: left; - border-left: none; - margin-left: @caret-margin; - margin-right: 0; - - .make-caret(right, top, bottom); - } - } - } -} - -@media (max-width: @grid-float-breakpoint-max) { - .dropdown-submenu { - .dropdown-menu { - position: static; - margin-top: 0; - border: 0; - box-shadow: none; - } - - > a:after { - margin-left: 6px; - display: inline-block; - vertical-align: middle; - - .make-caret(top, left, right); - } - } - - .dropdown-menu > .dropdown-submenu { - .dropdown > &, - .dropup > &, - .btn-group > & { - .make-nested-list(30px, 0, 4); - } - - .navbar-nav > .dropdown > & { - .make-nested-list(35px, 0, 4); - } - } -} diff --git a/less/mixins.less b/less/mixins.less deleted file mode 100644 index 3238017..0000000 --- a/less/mixins.less +++ /dev/null @@ -1,18 +0,0 @@ -.make-caret(@base, @left, @right) { - // dashed: fix caret size for Mozilla Firefox - border-@{base}: @caret-width-base dashed; - - border-@{left}: @caret-width-base solid transparent; - border-@{right}: @caret-width-base solid transparent; -} - -.make-nested-list(@offset, @i, @n) when (@i < @n) { - > .dropdown-menu > li { - &.dropdown-header, - > a { - padding-left: @offset + (10 * @i); - } - - .make-nested-list(@offset, @i + 1, @n); - } -} diff --git a/package.json b/package.json index 3b8591f..d1d28ec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bootstrap-submenu", - "version": "2.0.4", + "version": "3.0.0", "description": "Bootstrap Sub-Menus", "keywords": [ "bootstrap", @@ -17,29 +17,26 @@ "license": "MIT", "files": [ "dist", - "js/*.js", - "less" + "css", + "js" ], "main": "dist/js/bootstrap-submenu.js", "scripts": { - "test": "grunt" + "test": "npm run css; npm run js", + "css": "npm run css-compile; npm run css-minify", + "css-compile": "mkdir -p dist/css; cp -rf css/*.css dist/css/", + "css-minify": "cleancss --level 1 --source-map --source-map-inline-sources --output dist/css/$npm_package_name.min.css dist/css/$npm_package_name.css", + "js": "npm run js-compile; npm run js-minify", + "js-compile": "babel --out-dir dist/js/ js/*.js", + "js-minify": "uglifyjs --compress --output dist/js/$npm_package_name.min.js dist/js/$npm_package_name.js", + "release-zip": "cd dist/ && zip -r9 $npm_package_name-$npm_package_version-dist.zip * && mv $npm_package_name-$npm_package_version-dist.zip .." }, "devDependencies": { - "bootstrap": "~3.3.7", - "font-awesome": "~4.7.0", - "grunt": "~1.0.1", - "grunt-banner": "~0.6.0", - "grunt-contrib-clean": "~1.1.0", - "grunt-contrib-compress": "~1.4.3", - "grunt-contrib-copy": "~1.0.0", - "grunt-contrib-cssmin": "~2.2.1", - "grunt-contrib-jshint": "~1.1.0", - "grunt-contrib-less": "~1.4.1", - "grunt-contrib-uglify": "~3.3.0", - "grunt-ejs": "~0.3.0", - "grunt-jscs": "~2.5.0", - "highlight.js": "~9.12.0", - "jquery": "~3.3.0", - "load-grunt-tasks": "~3.5.2" + "@babel/cli": "7.0.0-beta.44", + "@babel/core": "7.0.0-beta.44", + "@babel/preset-env": "7.0.0-beta.44", + "bootstrap": "4.0.0", + "clean-css-cli": "4.1.11", + "uglify-js": "3.3.20" } }