Showing preview only (716K chars total). Download the full file or copy to clipboard to get everything.
Repository: phoenixwong/vue2-timepicker
Branch: master
Commit: 8f9371f9d8ce
Files: 29
Total size: 694.3 KB
Directory structure:
gitextract_knz350g7/
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE.md
├── MIGRATION.md
├── README.md
├── babel.config.js
├── demo/
│ ├── .gitignore
│ ├── README.md
│ ├── babel.config.js
│ ├── package.json
│ ├── public/
│ │ └── index.html
│ ├── src/
│ │ ├── App.vue
│ │ ├── assets/
│ │ │ ├── _variables.styl
│ │ │ └── demo.styl
│ │ ├── components/
│ │ │ ├── ConfigRow.vue
│ │ │ ├── OverlayPanel.vue
│ │ │ ├── Playground.vue
│ │ │ ├── SampleBlock.vue
│ │ │ └── Samples.vue
│ │ └── main.js
│ └── vue.config.js
├── dist/
│ ├── VueTimepicker.common.js
│ ├── VueTimepicker.css
│ ├── VueTimepicker.umd.js
│ └── demo.html
├── package.json
└── src/
├── index.js
└── vue-timepicker.vue
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Compiled source #
###################
*.com
*.class
*.dll
*.exe
*.o
*.so
# Packages #
############
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
# Cache and logs #
##################
Application/Runtime/Cache/
Application/Runtime/Logs/
Application/Runtime/Temp/
*.log
# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
~$*
.editorconfig
# NodeJS Packages #
###################
node_modules
yarn.lock*
package.lock*
# Bower Packages #
###################
bower
bower_components
# Test and Logs #
#################
npm-debug.log
yarn-debug.log*
yarn-error.log*
selenium-debug.log
test/unit/coverage
test/e2e/reports
# local env files #
###################
.env.local
.env.*.local
# Editor directories and files #
################################
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# Others #
###########
gh-pages
================================================
FILE: CHANGELOG.md
================================================
# CHANGELOG
> The Change Log of Vue2 Timepicker `vue2-timepicker`
## v 1.1.6
### New
- Support appending the dropdown menu to the document body with `append-to-body`
### Improvements
- In Manual Input mode, support jumping to the next token slot with a colon (`:`) or space (` `) key.
- Return full data on `blur` and `close` events as per the `change` event.
## v 1.1.5
### New
- Support changing dropdown direction with the `drop-direction` property. It accepts three string values: `"up"`, `"auto"` and `"down"` _(default)_.
- Additional `container-id` and `drop-offset-height` as helpers for the **"auto"** drop direction. Please check the documentation for more info.
## v 1.1.4
### New
- Support customized clear button and dropdown button with the `clearButton` and `dropdownButton` **v-slot** (Thanks to @jost-s).
- Added new `icon` **v-slot** for displaying an extra input icon.
- Added new `fixed-dropdown-button` property, to make the dropdown button always visible.
## v 1.1.3
### Improvements
- Enhanced `hide-dropdown` feature -- When the dropdown is hidden by default, users can choose to open the dropdown by clicking the triangle button "▾" (Thanks to @jost-s).
- Refined `focus` and `blur` event.
- Minor fixes for the Advanced Keyboard mode.
## v 1.1.2
### New
More powerful `format` string parameter. E.g., you can hide the "hour" column by setting `format="mm:ss"`, or make AM/PM the first column by `format="A hh:ss"`, no extra CSS hacking needed. Please check the Demo page for more examples.
### Improvements
- Support `shift+tab` to navigate to the previous token slot in the Manual Input mode (Thanks to @jost-s).
- Other minor keyboard navigation enhancements for Manual Input mode
## v 1.1.1
### Improvements
Instant feedback after manual input. Plus, add a new `manual-input-timeout` property to help set up the timeout for continuous input (Thanks to @jost-s).
#### Notes for Contributors
We've upgraded to use vue-cli **v4** in this version. Please check the CONTRIBUTING.md for more info.
## v 1.1.0
### New
- Support manually input values with the `manual-input` toggle.
- Enable to hide the dropdown menu with `hide-dropdown` in Manual Input (`manual-input`) mode.
- Added conditional helper classes `is-empty`, `invalid` and `all-selected` to the `<input>` element.
- Change the `<input>` border to red color when user input is invalid. E.g., when it contains a disabled hour value. You can mute this auto-styling by adding `"skip-error-style"` to `input-class`.
- Add support to the `autocomplete` attribute.
- Emit `error` event when the input value becomes invalid.
- Emit `focus` and `blur` events to help to identify the focus/blur state. Useful when the dropdown is force hidden by `hide-dropdown`.
### Improvements
Enable seamless loop from the start or end of a column in `advanced-keyboard` mode.
## v 1.0.8
### Improvements
Keep the dropdown menu open when mouse drag on the hour/minute/second list's scrollbar handler.
## v 1.0.7
### Fixes
Fixes `placeholder` not dynamically updated issue in some cases (Thanks to @ObsidianTech).
### Improvements
Vertical alignment refined for the clear button across different browsers.
## v 1.0.6
### New
Added `auto-scroll` feature.
### Improvements
On Advanced Keyboard mode, auto-focus on the selected value (if any) in priority.
## v 1.0.5
### Fixes
Fixes the Advanced Keyboard tab navigating feature on Firefox
## v 1.0.4
### Improvements
- Adjust the default value of `blur-delay` to 300ms. (Thanks to @rjurado01).
- Added _Array_ and _Object_ types support to `input-class`.
## v 1.0.3
### New
Added `lazy` event mode. (Thanks to @VictorCazanave)
## v 1.0.2
### New
- Support customized labels for the hour, minute, second, and APM pickers (Thanks to @maritaria).
- Support setting customized text to replace the `am`/`pm` (`AM`/`PM`) string in the UI.
- Added `input-width` property to help to adjust Timepicker's width with ease.
### Improvements
Added more guiding notes for SSR usage. (Thanks to @oj-recit)
## v 1.0.1
### Fixes
Fixes the _String_ form `v-model` support on Edge and Safari
## v 1.0.0
### Breaking Changes
**⚠️ IMPORTANT:** The default **import** source in `v1.0.0+` is different from the `v0.x` versions.
From `v1.0.0+`, CSS is excluded from the main source. Please import the CSS file separately.
```javascript
// v1.0.0+
//
import VueTimepicker from 'vue2-timepicker'
// -> Imports JS file in UMD form
// CSS
import 'vue2-timepicker/dist/VueTimepicker.css'
```
Comparing to:
```javascript
// While in the v0.x versions
import VueTimepicker from 'vue2-timepicker'
// -> Imports the *.vue Single File Component together with CSS
```
Please check the [Documentation](https://github.com/phoenixwong/vue2-timepicker/blob/master/README.md#get-started) for more available import formats.
### New
- Support using _String_ value in `v-model`.
- New `minute-range` and `second-range` support. Companioned with `hide-disabled-minutes` and `hide-disabled-seconds`.
- New `hide-disabled-items` property for hiding **all** excluded items (hour, minute and seconds) at a time.
- New `close-on-complete` for automatically close the dropdown when the user finishes selecting **all** of the required fields.
- Added `advanced-keyboard` support for Arrow Keys navigation and Space/Enter key selection.
- New `tabindex` property support, which will be assigned to the `<input type="text">` within the component.
- Added `debug-mode` to help developers investigating the input -> output process.
### Fixes
Added ES "module" and other version fields in _package.json_ to resolving more loader issues. (Thanks to @Trainmaster)
### Improvements
When `hour-range` is set in a 12-hour format Timepicker, recheck the selected hour's validity after user switching "AM/PM" from the dropdown.
## v 0.2.2
### Fixes
Fixes `v-model` watcher for cases like changing the input value programmatically (non-user behavior).
### Improvements
Added `displayTime` in the return data of `change` event.
## v 0.2.1
### New
- New `input-class` support. The custom input class will be assigned to the `<input type="text">` within the component. (Thanks to @marufmax)
- Add support to `placeholder`, just like other regular form elements
### Improvements
Refined `@click.stop` logic
### Fixes
Fixes possible loader issue in some Webpack configs (Thanks to @RaphaelJ)
## v 0.2.0
### Breaking Changes
- Upgraded to support more current **vue** (2.6.10) and **vue-cli** (3.9.0) with Webpack 4.
### New
- New `hour-range` support. Added capability to show which hours are available and disabled the rest.
- New `hide-disabled-hours`. The best companion of `hour-range`, for you to hide unwanted hours in the hour picker.
- New `disabled` parameter. To disable dropdown picker and clear button in the UI.
- Emit `open` and `close` events to help tracking the dropdown toggle status. (Thanks to @tprashan)
### Improvements
- Put `12` before `1` in the hour select for 12-hour format (`hh` and `h`). It will be more natural, especially when paired with `hour-range`.
- Support `name` parameter as regular form inputs. (Thanks to @dilipgurung)
## v 0.1.4
### Fixes
Added stop propagation `.stop` to click events
## v 0.1.3
### Improvements
Add support to `<label for="...">` (Thanks to @Reached)
```html
<!-- Sample -->
<label for="yourID">Your Label Text</label>
<vue-timepicker id="yourID"></vue-timepicker>
```
## v 0.1.2
Release the `dist` files
## v 0.1.1
The first notable release of Vue2 Timepicker
================================================
FILE: CONTRIBUTING.md
================================================
# Contribution
Please feel free to fork and help developing.
```bash
# Install dependencies
yarn install
# Init development dependencies
yarn dev:init
# Start developing. Serve with hot reload at localhost:8080
yarn dev
```
For detailed explanation on how things work, checkout the [Vue Cli Guide](https://cli.vuejs.org/guide/).
**BREAKING CHANGES**
- Start from `^0.2.0`, we develop Demo pages with [**Yarn**](
https://yarnpkg.com/), [**Pug**](https://pugjs.org/), and [**Stylus**](http://stylus-lang.com/)
- Upgraded to **@vue/cli v4** from `^1.1.1`.
**NOTE**
If you have trouble running `yarn dev` after the _^1.1.1_ upgrade, please try the following process:
1. Remove the existing `node_modules` folder and the `yarn.lock` in this repository's **root** directory.
2. Next, remove the `node_modules` folder and the `yarn.lock` in the **/demo** directory as well.
3. Go back to the repository's root, run `yarn install`, and `yarn dev:init` again.
---
### Watchdogs




================================================
FILE: LICENSE.md
================================================
MIT License
Copyright (c) 2019 Phoenix Wong
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: MIGRATION.md
================================================
# Table of Contents
- [Migrating from Vue 1.x vue-timepicker](https://github.com/phoenixwong/vue2-timepicker/blob/master/MIGRATION.md#migrating-from-vue-1x-vue-timepicker)
- [Migrating from Bower to Yarn or NPM](https://github.com/phoenixwong/vue2-timepicker/blob/master/MIGRATION.md#migrating-from-bower-to-yarn-or-npm)
# Migrating from Vue 1.x vue-timepicker
There are bunch of [notable changes in Vue2](http://vuejs.org/guide/migration.html), and quite some of the key features our original `vue-timepicker` has been relying on, got deprecated since 2.0. So here we are, a brand new version compatible with Vue 2.x.
## Crucial changes
### Use `v-model` Instead of `:time-value.sync`
The `.sync` modifier on `v-bind` has been deprecated ([source](http://vuejs.org/guide/migration.html#once-and-sync-Modifiers-on-v-bind-removed)), hence the original `:time-value.sync` binding is not going to work anymore.
However, thanks to the awesome Vue2.0 feature, which now has great support for `v-model` on custom components, you can simply replace those sync properties with `v-model`.
```html
<!-- Vue 1.x -->
<vue-timepicker :time-value.sync="yourTimeValue"></vue-timepicker>
<!-- Vue 2.x version -->
<vue-timepicker v-model="yourTimeValue"></vue-timepicker>
```
### No More `vue-timepicker-update` Event
The `$dispatch` event `vue-timepicker-update` been depending on, together with the `events` option, got removed in Vue2 either ([source 1](http://vuejs.org/guide/migration.html#dispatch-and-broadcast-replaced), [source 2](http://vuejs.org/guide/migration.html#events-option-removed)). Please switch to `@change` event handler instead -- check the [Documentation](https://github.com/phoenixwong/vue2-timepicker#method-2-add-change-event-handler) for detail example.
## Minor Changes
### Replace `$arguments` with `$event` in the `change` event handler
If you're using `change` event handler **with** custom arguments, please replace the old `$arguments` parameter with `$event`
```html
<!-- Vue 1.x -->
<vue-timepicker :time-value.sync="yourTimeValue" @change="changeHandler($arguments, 'foo', 'bar')"></vue-timepicker>
<!-- Vue 2.x version -->
<vue-timepicker :time-value.sync="yourTimeValue" @change="changeHandler($event, 'foo', 'bar')"></vue-timepicker>
```
Whereas the `change` event handler *without* custom arguments is intact.
### Get Rid of the Array Wrapper `[]` in `change` Event Data
In the example above, when reading event data from the `changeHandler` in 1.x, the data structure will be --
```javascript
// Vue 1.x
[
{
data: {
HH:...,
mm:...,
...
}
}
]
```
In the 2.x version, we can say goodbye to the `[]` wrapper --
```javascript
// Vue 2.x version
{
data: {
HH:...,
mm:...,
...
}
}
```
### The `change` event now returns full values
In the Vue 1.x version, if you have `time-value` in sync, `change` event will only return values from your predefined tokens. Whereas the new 2.x version will always return a full value package containing all supported tokens.
For example, if you have a binding value defined in the form of "HH:mm:ss"
```javascript
// predefined data sample
data: function () {
return {
yourTimeValue: {
HH: "10",
mm: "05",
ss: "00"
},
...
}
}
```
When the picker is set to "14:30:15" later --
```javascript
// Vue 1.x
// - only returns predefined tokens ('HH', 'mm' and 'ss')
{
HH: "14",
mm: "30",
ss: "15"
}
// Vue 2.x version
// - returns All supported tokens
{
HH: "14",
H: "14",
hh: "14",
a: "am",
A: "AM",
h: "14",
kk: "14",
k: "14",
m: "30",
mm: "30",
s: "15",
ss: "15"
}
```
## Miscellaneous
There will be **no** standalone ES5 script in the 2.x version.
---
# Migrating from Bower to Yarn or NPM
Because [Bower](https://bower.io/) itself stopped maintaining since 2017, VueTimepicker drops support for Bower from version `0.2.0+`.
Please check Bower's official guidelines for [How to migrate away from Bower?](https://bower.io/blog/2017/how-to-migrate-away-from-bower/)
================================================
FILE: README.md
================================================
# Vue2 Timepicker




---
💡 Dead repo recharged 🔋
---
A dropdown time picker (hour|minute|second) for **Vue 2.x**, with flexible time format support.
## Demo
You can see the **Vue2 Timepicker** in action in the [Demo Page](https://phoenixwong.github.io/vue2-timepicker/)
## Migration
Please check [MIGRATION.md](https://github.com/phoenixwong/vue2-timepicker/blob/master/MIGRATION.md) for basic guidelines if you are about to:
- Migrate from the Vue 1.x version **[vue-time-picker](https://github.com/phoenixwong/vue-timepicker)**
- Migrate from Bower to Yarn or NPM (Vue2 Timepicker `v0.1.x` -> `v0.2.0+`)
## Dependencies
[Vue.js](http://vuejs.org/) 
## Installation
```bash
yarn add vue2-timepicker
```
```bash
npm install vue2-timepicker --save
```
> NOTE: We stop Bower support from `0.2.0+`, please check [MIGRATION.md](https://github.com/phoenixwong/vue2-timepicker/blob/master/MIGRATION.md#migrating-from-bower-to-yarn-or-npm) for migration guidelines.
## Get Started
### **Step 1:** Import VueTimepicker
#### **Option A:** Import component JS and CSS
```javascript
// Main JS (in UMD format)
import VueTimepicker from 'vue2-timepicker'
// CSS
import 'vue2-timepicker/dist/VueTimepicker.css'
```
#### **Option B:** Choose any bundle version base on your needs
**Javascript**
```javascript
// CommonJS
import VueTimepicker from 'vue2-timepicker/dist/VueTimepicker.common.js'
// UMD
import VueTimepicker from 'vue2-timepicker/dist/VueTimepicker.umd.js'
// UMD Minified
import VueTimepicker from 'vue2-timepicker/dist/VueTimepicker.umd.min.js'
```
**CSS**
```css
@import 'vue2-timepicker/dist/VueTimepicker.css';
/* Or, with node_module alias path like: */
@import '~vue2-timepicker/dist/VueTimepicker.css';
/*
NOTE: the path alias to `node_modules` differs between bundlers.
Please change the `~` to any alias that works with your environment.
*/
```
**Single File Component**
```javascript
// The *.vue file with CSS included
import VueTimepicker from 'vue2-timepicker/src/vue-timepicker.vue'
// NOTE: In some cases, it requires additional workarounds in the bundler's config
```
#### **SSR Usage**
```javascript
// Import the *.vue file (CSS included)
import VueTimepicker from 'vue2-timepicker/sfc'
// Note the `/sfc` suffix here
```
If your server-side renderer cannot recognize the `/sfc` alias, please try --
```javascript
// Manually point to the `/src` folder
import VueTimepicker from 'vue2-timepicker/src'
// Or, to the specific file name
import VueTimepicker from 'vue2-timepicker/src/vue-timepicker.vue'
```
### **Step 2**: Include VueTimepicker in your component
```javascript
var yourComponent = new Vue({
components: { VueTimepicker },
...
})
```
### **Step 3**: Put `vue-timepicker` in your component's template
Then, you can introduce the `vue-timepicker` tag anywhere you like in your component's template
```html
<vue-timepicker></vue-timepicker>
```
## Basic Usage
### Base
```html
<!-- Default to 24-Hour format HH:mm -->
<vue-timepicker></vue-timepicker>
```
### Customized Time Format
```html
<!-- Show seconds picker -->
<vue-timepicker format="HH:mm:ss"></vue-timepicker>
<!-- 12-hour format, with AM/PM picker -->
<vue-timepicker format="hh:mm A"></vue-timepicker>
<!-- 12-hour format, with seconds picker and am/pm picker -->
<vue-timepicker format="hh:mm:ss a"></vue-timepicker>
```
VueTimepicker recognizes the following tokens in the format string
Section | Token | Output
---------- | ----- | ---------------
**AM/PM** | A | AM PM
| a | am pm
**Hour** | H | 0 1 ... 22 23
| HH | 00 01 ... 22 23
| h | 1 2 ... 11 12
| hh | 01 02 ... 11 12
| k | 1 2 ... 23 24
| kk | 01 02 ... 23 24
**Minute** | m | 0 1 ... 58 59
| mm | 00 01 ... 58 59
**Second** | s | 0 1 ... 58 59
| ss | 00 01 ... 58 59
> If not set, the `format` string is default to "HH:mm"
### Customized Picker Interval
```html
<!-- Show minute picker's value in the form of 0, 5, 10, ... 55, 60 -->
<vue-timepicker :minute-interval="5"></vue-timepicker>
<!-- Show second picker's value in the form of 0, 10, 20, ... 50, 60 -->
<vue-timepicker :second-interval="10"></vue-timepicker>
<!-- Bind interval config with your own data variable -->
<vue-timepicker :minute-interval="yourMinuteInterval"></vue-timepicker>
```
## Data Binding
### Bind Value with `v-model`
From `v1.0.0+`, timepicker's `v-model` accepts value in both _Object_ (default) and _String_ format. The `v0.x` versions only support _Object_ form.
#### Set Initial Value
For example, if you want to set "10:05:00" ("HH:mm:ss" format) as the initial value of vue-timepicker:
```javascript
const yourComponent = new Vue({
components: { VueTimepicker },
data () {
return {
// Object form
yourTimeValue: {
HH: '10',
mm: '05',
ss: '00'
},
// String form
yourStringTimeValue: '10:05:00',
...
}
},
...
})
```
Both forms lead to the same result.
```html
<!-- Object form -->
<vue-timepicker v-model="yourTimeValue" format="HH:mm:ss"></vue-timepicker>
<!-- String form -->
<vue-timepicker v-model="yourStringTimeValue" format="HH:mm:ss"></vue-timepicker>
```
#### Set Empty Initial Value
When the initial value is completely unknown:
```javascript
data () {
return {
// Will be rendered as Object form
yourEmptyValue: {},
emptyValueToo: undefined,
emptyValueAsWell: null,
// Will be taken into String form
yourEmptyStringValue: ''
}
}
```
#### Set Partially-Known Initial Value
For instance, if you want to set the initial hour value to **8 pm** and leave the rest slots empty:
```javascript
data () {
return {
// OBJECT FORM
// Default 24-Hour
timeValue: {
HH: '20',
mm: ''
},
// 12-Hour with seconds
timeValueWithSec: {
h: '8',
mm: '',
ss: '',
A: 'PM'
},
// STRING FORM
// Default 24-Hour + String value
stringTimeValue: '20:mm',
// 12-Hour with seconds + String value
stringTimeValueWithSec: '8:mm:ss PM'
}
}
```
```html
<!-- OBJECT FORM -->
<!-- Default 24-Hour -->
<vue-timepicker v-model="timeValue"></vue-timepicker>
<!-- 12-Hour with seconds -->
<vue-timepicker v-model="timeValueWithSec" format="h:mm:ss A"></vue-timepicker>
<!-- STRING FORM -->
<!-- Default 24-Hour + String value -->
<vue-timepicker v-model="stringTimeValue"></vue-timepicker>
<!-- 12-Hour with seconds + String value -->
<vue-timepicker v-model="stringTimeValueWithSec" format="h:mm:ss A"></vue-timepicker>
```
### Get Time Picker's Current Value
#### Get value from `v-model`
You can either read the binding `v-model` value anytime or add a handler to deal with the `input` event from vue-timepicker.
```html
<vue-timepicker v-model="yourTimeValue" format="HH:mm:ss" @input="inputHandler"></vue-timepicker>
```
```javascript
{
data () {
return {
yourTimeValue: {
HH: '10',
mm: '05',
ss: '00'
},
...
}
},
methods: {
inputHandler (eventData) {
console.log(eventData)
}
}
}
```
In this case, we set the initial value (_yourTimeValue_) to "10:05:00". Then, open the dropdown picker and pick a new time, like setting it to "14:30:15" for example.
```javascript
// In `inputHandler`:
// console.log outputs -> {HH: "14", mm: "30", ss: "15"}
```
### Read Data From `change` Event
```html
<!-- A: No argument -->
<vue-timepicker v-model="yourTimeValue" @change="changeHandler"></vue-timepicker>
<!-- B: Custom arguments -->
<vue-timepicker v-model="yourTimeValue" @change="otherChangeHandler($event, 'foo', 42)"></vue-timepicker>
```
```javascript
// A: No argument
changeHandler (eventData) {
console.log(eventData)
// -> {data: {HH:..., mm:... }, displayTime: "HH:mm"}
}
// B: Custom arguments
otherChangeHandler (eventData, yourArg1, yourArg2) {
console.log(eventData)
// -> {data: {HH:..., mm:... }, displayTime: "HH:mm"}
console.log(yourArg1)
// -> 'foo'
console.log(yourArg2)
// -> 42
}
```
Unlike `v-model` and `input` event, which only return the defined time tokens you provided in the binding variable, the `change` event delivers **all** supported formats.
In the example above, after the user set values to "14:30:15" in the picker, `change` event returns the following data:
```javascript
// `@change` event data
{
data: {
HH: "14",
H: "14",
hh: "14",
a: "am",
A: "AM",
h: "14",
kk: "14",
k: "14",
m: "30",
mm: "30",
s: "15",
ss: "15"
},
// extra `displayTime` added since v0.2.2
displayTime: "14:30:15"
}
```
Whereas the `v-model` / `input` only return the data with defined tokens
```javascript
// Previously defined variable (`yourTimeValue` in this case) as {HH:..., mm:..., ss:...}
// Hence, the `v-model` returns:
{
HH: "14",
mm: "30",
ss: "15"
}
```
## Advance Usage
### Hide Clear Button
```html
<vue-timepicker hide-clear-button></vue-timepicker>
```
Enable to hide the "×" clear button on the right-hand side. Users can still pick new values from the dropdown, but they cannot erase any selected data.
### Disable Picker
```html
<vue-timepicker disabled></vue-timepicker>
```
Fully disable both dropdown picker and the "×" clear button in the UI, to prevent users from changing any values again.
### Close on Complete
Automatically close the dropdown when the user finishes selecting **all** of the required fields.
```html
<vue-timepicker close-on-complete></vue-timepicker>
```
### Auto-Scroll
```html
<vue-timepicker auto-scroll></vue-timepicker>
```
Auto-scroll to selected values on dropdown open. It works with both:
- Programmatically defined value. E.g., the initial value from `v-model`
- Values manually picked by the user.
### Define Hour Range
Sometimes you may want to limit hours picker to a specific range. The `hour-range` parameter is here to help.
```html
<!-- 24-Hour Format -->
<vue-timepicker :hour-range="[5, [8, 12], [14, 17], 19]"></vue-timepicker>
<!-- >> Equals to :hour-range="[5, 8, 9, 10, 11, 12, 14, 15, 16, 17, 19]" -->
<!-- 12-Hour Format -->
<vue-timepicker :hour-range="['7a', '9a', '11a', '1p', ['3p', '5p'], '7p']" format="hh:mm a">
<!-- >> Equals to :hour-range="['7a', '9a', '11a', '1p', '3p', '4p', '5p', '7p']" -->
```
### Set Minute and Second Range
Similar to `hour-range`, you can determine values in the minutes and seconds dropdown by using `minute-range` and `second-range`.
```html
<!-- Minute range -->
<vue-timepicker :minute-range="[0, 6, [10, 30], 42, 50]"></vue-timepicker>
<!-- >> Active Items: 00, 06, 10, 11, 12, 13, ..., 27, 28, 29, 30, 42, 50 -->
<!-- Second range -->
<vue-timepicker format="H:m:s" :second-range="[0, 6, [10, 30], 42, 50]"></vue-timepicker>
<!-- >> Active Items: 0, 6, 10, 11, 12, 13, ..., 27, 28, 29, 30, 42, 50 -->
```
When implemented together with `minute-interval` and `second-interval`, the customized intervals take the priority.
```html
<!-- Minute range + 5-minute interval -->
<vue-timepicker :minute-range="[0, 6, [10, 30], 42, 50]" :minute-interval="5"></vue-timepicker>
<!-- >> Active Items: 00, 10, 15, 20, 25, 30, 50 -->
<!-- Second range + 10-second interval-->
<vue-timepicker format="H:m:s" :second-range="[0, 6, [10, 30], 42, 50]" :second-interval="10"></vue-timepicker>
<!-- >> Active Items: 0, 10, 20, 30, 50 -->
```
### Hide Disabled Items
There're four kinds of helper properties to let you hide the values excluded by `hour-range`, `minute-range`, and `second-range`.
- **hide-disabled-items**: Hide **all** disabled items - hour, minute, and seconds.
- **hide-disabled-hours**: Hide disabled **hour** values only.
- **hide-disabled-minutes**: Hide disabled **minute** values only.
- **hide-disabled-seconds**: Hide disabled **second** values only.
```html
<!-- `hide-disabled-hours` sample -->
<vue-timepicker :hour-range="[5, [8, 12], [14, 17], 19]" hide-disabled-hours></vue-timepicker>
```
Here we take the `hide-disabled-hours` as an example. It's a pair with the `hour-range` parameter. In this case, the hour picker hides the invalid hours (_0, 1, 2, 3, 4, 6, 7, 13, 18, 20, 21, 22, 23_) and display the valid hours (_5, 8, 9, ..._) only.
### Advanced Keyboard Support
Basic keyboard support includes:
- **Tab**: Focus or blur the Timepicker
- **Esc**: Close the dropdown
Advance Keyboard support (enabled with `advanced-keyboard`):
- **Arrow Keys**: Navigate between valid (non-disabled) values and columns
- **Space** or **Enter**: Select the focusing item
```html
<vue-timepicker advanced-keyboard></vue-timepicker>
```
Please be aware that after putting the `advanced-keyboard` on, hundreds of additional keyboard event listeners are going to be attached to the component. The amount of listeners depends on how many hours, minutes, and seconds value you enabled in the current Timepicker.
### Blur Delay
```html
<!-- Unit: million second -->
<vue-timepicker :blur-delay="500"></vue-timepicker>
```
Sets the blur delay time for the dropdown. Defaults to `300` if not set.
### Manual Input Support
```html
<vue-timepicker manual-input></vue-timepicker>
```
Let users add or change values through the `<input>` box besides the dropdown picker.
### Manual Input Timeout
```html
<!-- Unit: million second -->
<vue-timepicker :manual-input-timeout="1500"></vue-timepicker>
```
Works with **manual-input** mode. It sets the timeout for continuous input. Defaults to `1000` if not set.
**How It Works?**
For example, when a user focuses on the **hour** slot (`HH`) of a `"HH:mm"` formatted Timepicker (with the default value `1000`):
- **Case 1:** User first inputs `1`, and then inputs `2` _500ms_ later -> Timepicker takes `12` as the final value and set it to the `"HH"` slot.
- **Case 2:** User inputs `1`, and then presses the key `2` _1200ms_ later -> Timepicker takes `2` as the final value and set it to `02` for the `"HH"` slot.
### Hide Dropdown
> **NOTE:** To use this feature, you MUST ENABLE the `manual-input` mode _(v.1.1.0+)_ in the first place.
It makes the dropdown picker hidden by default.
```html
<vue-timepicker manual-input hide-dropdown></vue-timepicker>
```
Users can still choose to open the dropdown by clicking the triangle ("▾") button on the right. _(v.1.1.3+)_
### Fixed Dropdown Button
```html
<vue-timepicker fixed-dropdown-button></vue-timepicker>
```
Make the dropdown button always visible in the UI. _(v.1.1.4+)_
### Drop Direction
Change dropdown direction when needed _(v.1.1.5+)_. Accepting values:
- **down**: Default value.
- **up**: Force open the dropdown above the input.
- **auto**: Auto detects available height and opens the dropdown on top if there are not enough spaces below the input.
```html
<!-- Force drop up -->
<vue-timepicker drop-direction="up"></vue-timepicker>
<!-- Auto drop direction -->
<vue-timepicker drop-direction="auto"></vue-timepicker>
```
#### Container ID
Works with `drop-direction="auto"`. It defines the parent container where the timepicker should calculate the free spaces from. If this value is not set, timepicker will watch `document.body` instead.
```html
<!-- Parent Container ID: "auto-dropdown-containter" -->
<div id="auto-dropdown-containter">
<!-- Defined Container -->
<vue-timepicker drop-direction="auto" container-id="auto-dropdown-containter"></vue-timepicker>
<!-- Default (document body) -->
<vue-timepicker drop-direction="auto"></vue-timepicker>
</div>
```
#### Drop Offset Height
Works with `drop-direction="auto"` either. Defaults to `160` (unit: _px_) if the value is not set.
```html
<!--
When the available bottom space is less than 200px,
open the dropdown above the input.
-->
<vue-timepicker drop-direction="auto" :drop-offset-height="200"></vue-timepicker>
```
### Lazy Event Mode
```html
<vue-timepicker lazy></vue-timepicker>
```
When `lazy` event mode is toggled on, only an actual user behavior can trigger the `input` and `change` events. Which are:
- The user opened the dropdown and picked a new value
- The user clicked the ("×") clear button
- The user inputted a new value or clear the existing value in the Manual Input mode
In other words, on `lazy` mode, Timepicker won't emit `input` and `change` events on mounted, nor after the value got modified programmatically.
### Append To Body
Append the dropdown menu to the end of the document `<body>`. Try this if you have `z-index` or `overflow` layout issue with the dropdown.
```html
<vue-timepicker append-to-body></vue-timepicker>
```
The body-appended dropdown's CSS class is `vue__time-picker-dropdown`. Its default `z-index` is `100`. You can change the value by adding the following style in your app --
```css
/* E.g. set the z-index to 5000 */
.vue__time-picker-dropdown {
z-index: 5000;
}
```
**NOTE**: If you have to override some of the CSS styles within the dropdown, you will need to update their selectors' class names as well. Simply change any `.vue__time-picker .dropdown` selector to `.vue__time-picker-dropdown`.
For example, when you have a customized background color set for selected values:
```css
/* Default override (not using "append-to-body") */
.vue__time-picker .dropdown ul li:not([disabled]).active {
background: steelblue;
}
/* When using "append-to-body" */
.vue__time-picker-dropdown ul li:not([disabled]).active {
background: steelblue;
}
```
### Enable Debug Mode
```html
<vue-timepicker debug-mode></vue-timepicker>
```
It's aimed to help developers to investigate the input -> output process. When debug mode is toggled **on**, you can see extra `DEBUG: ...` logs coming through the console window as you interact with the vue-timepicker.
Let's create a "bug" here as an example --
```html
<!-- Manual Bug Sample: Define timepicker with format "h:mm:ss A" -->
<vue-timepicker v-model="yourStringValue" format="h:mm:ss A" debug-mode></vue-timepicker>
```
```javascript
{
data () {
return {
// Manual Bug Sample:
// Should be '3:mm:05 A' but oops.. the finger slipped
yourStringValue: 'e:mm:05 A'
}
}
}
```
Then, in the console window, you should see a debug log saying:
```console
DEBUG: The input string in "v-model" does NOT match the "format" pattern
format: h:mm:ss A
v-model: e:mm:05 A
```
## Main Props API Overview
Prop | Type | Required | Default Value
------------------------- | ------------------ | -------- | -------------
**v-model** | _Object_, _String_ | no | _undefined_
**format** | _String_ | no | "HH:mm"
**minute-interval** | _Number_ | no | _undefined_
**second-interval** | _Number_ | no | _undefined_
**hide-clear-button** | _Boolean_ | no | false
**disabled** | _Boolean_ | no | false
**close-on-complete** | _Boolean_ | no | false
**auto-scroll** | _Boolean_ | no | false
**hour-range** | _Array_ | no | _undefined_
**minute-range** | _Array_ | no | _undefined_
**second-range** | _Array_ | no | _undefined_
**hide-disabled-hours** | _Boolean_ | no | false
**hide-disabled-minutes** | _Boolean_ | no | false
**hide-disabled-seconds** | _Boolean_ | no | false
**hide-disabled-items** | _Boolean_ | no | false
**advanced-keyboard** | _Boolean_ | no | false
**blur-delay** | _Number_ | no | 300
**manual-input** | _Boolean_ | no | false
**manual-input-timeout** | _Number_ | no | 1000
**hide-dropdown** | _Boolean_ | no | false
**fixed-dropdown-button** | _Boolean_ | no | false
**drop-direction** | _String_ | no | "down"
**container-id** | _String_ | no | _undefined_
**drop-offset-height** | _Number_ | no | 160
**lazy** | _Boolean_ | no | false
**append-to-body** | _Boolean_ | no | false
**debug-mode** | _Boolean_ | no | false
## Input Props API
Prop | Type | Required | Default Value
------------------| --------------------------- | -------- | -------------
**id** | _String_ | no | _undefined_
**name** | _String_ | no | _undefined_
**placeholder** | _String_ | no | _undefined_
**tabindex** | _Number_ | no | 0
**autocomplete** | _String_ | no | 'off'
**input-class** | _String_, _Array_, _Object_ | no | _undefined_
**input-width** | _String_ | no | '10em'
Timepicker supports `id`, `name`, `placeholder`, and `tabindex` like common form elements. These values are assigned to the `<input type="text" class="display-time">` within the component.
### Input `id`, `name` and `tabindex`
```html
<!-- id -->
<vue-timepicker id="myFirstPicker"></vue-timepicker>
<!-- name -->
<vue-timepicker name="nameInForm"></vue-timepicker>
<!-- tabindex -->
<vue-timepicker :tabindex="5"></vue-timepicker>
```
### Input `placeholder`
When `placeholder` is undefined, timepicker takes the determined format string instead.
```html
<!-- placeholder is set -->
<vue-timepicker placeholder="Start Time"></vue-timepicker>
<!-- -> "Start Time" -->
<!-- placeholder not set -->
<vue-timepicker format="hh:mm A"></vue-timepicker>
<!-- -> "hh:mm A" -->
<!-- both placeholder and format are not set -->
<vue-timepicker></vue-timepicker>
<!-- -> "HH:mm" -->
```
### Input `autocomplete` Attribute
> **NOTE:** To use this property, you MUST ENABLE the `manual-input` mode _(v.1.1.0+)_ in the first place.
```html
<!-- In Vue Template -->
<vue-timepicker name="starttime" autocomplete="on" manual-input></vue-timepicker>
```
```html
<!-- HTML result -->
<span class="vue__time-picker time-picker">
<input class="display-time" name="starttime" type="text" autocomplete="on">
<!-- ... -->
</span>
```
When enabled, it accepts any string value supported by the HTML input `autocomplete` attribute. The value is assigned to the embedding text `<input>`, which means it follows form autofill rules and configs set in the browser level. For example, most of the browsers require the input to have a `name` and/or `id` attribute. Some browsers, like Firefox, demand the input to be a descendant of a `<form>` element.
Please refer to the [HTML documentation](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill) and the developer guideline of each browser for more information (i.e., [MDN docs here](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete)).
### The `input-class`
The `input-class` is assigned to the text input within the component as well.
```html
<!-- Set your own `input-class` in the Vue template -->
<vue-timepicker input-class="my-awesome-picker"></vue-timepicker>
```
```html
<!-- HTML result -->
<span class="vue__time-picker time-picker">
<input class="display-time my-awesome-picker" type="text" readonly="readonly">
<!-- ... -->
</span>
```
Start from `v1.0.4`, besides _String_ format, `input-class` accepts value in _Array_ and _Object_ type as well.
```html
<!-- String type -->
<vue-timepicker input-class="your-awesome-timepicker i-am-vue2-timepicker"></vue-timepicker>
<!-- Array type -->
<vue-timepicker :input-class="['your-awesome-timepicker', 'i-am-vue2-timepicker']"></vue-timepicker>
<!-- Object type -->
<vue-timepicker :input-class="{
'your-awesome-timepicker': true,
'foo': false,
'i-am-vue2-timepicker': true,
'bar': false
}"></vue-timepicker>
```
```html
<!-- All of the three samples above return the same result in rendered HTML -->
<span class="vue__time-picker time-picker">
<input class="display-time your-awesome-timepicker i-am-vue2-timepicker" type="text" readonly="readonly">
<!-- ... -->
</span>
```
### The `input-width`
The `input-width` helps you to adjust both the `<input>` and the dropdown picker's width without overriding the CSS style on your own. It accepts any valid CSS width values like `8em`, `200px`, etc.
```html
<!-- In `px` -->
<vue-timepicker input-width="100px"></vue-timepicker>
<!-- In `em` -->
<vue-timepicker input-width="12em" format="HH:mm:ss"></vue-timepicker>
```
## Events API
Event | Arguments | Description
-------------- | -------------- | ----------------------
**input** | (_value_) | Emit after value changes
**change** | (_eventData_) | Emit after value changes
**open** | | Emit when the dropdown opens
**close** | (_eventData_) | Emit when the dropdown closes
**focus** | | Emit when the user start focusing on the `<input>`
**blur** | (_eventData_) | Emit when the user blurs the `<input>`
**error** | (_eventData_) | Emit when the input value becomes invalid
### The `open` and `close` Event of the Dropdown Picker
Help to identify the current status of the dropdown picker
```javascript
data () {
return {
dropdownStatus: 'closed'
}
}
```
```html
<p>Dropdown Status: I'm {{dropdownStatus}}!</p>
<vue-timepicker @open="dropdownStatus = 'opened'" @close="dropdownStatus = 'closed'"></vue-timepicker>
```
### The `focus` and `blur` Event
It works with the Manual Input mode, aimed to identify the focus/blur state of the `<input>` box. Specially useful in cases where the dropdown is force hidden by `hide-dropdown`.
```javascript
data () {
return {
focusState: 'blurred'
}
}
```
```html
<p>Focus State: {{focusState}}</p>
<vue-timepicker manual-input hide-dropdown @focus="focusState = 'focused'" @blur="focusState = 'blurred'"></vue-timepicker>
```
### The `error` event
Starts from `v.1.1.0+`, Timepicker will emit an `error` event when the current input value becomes invalid. E.g., when it contains an hour value that is not in the `hour-range` list or a minute value that doesn't fit in the `minute-interval`.
```html
<!-- Got the `hour-range` and `minute-interval` set -->
<!-- And add a hanlder to pick up the "error" event -->
<vue-timepicker format="H:mm:ss" v-model="erroredInputSample" :hour-range="[8, 9, 10, 11]" :minute-interval="5" @error="errorHanlder"></vue-timepicker>
```
```javascript
data () {
return {
erroredInputSample: { H: '5', mm: '03', ss: '00' }
// NOTE:
// H: '5' -> invalid. Value is not in the `hour-range` list
// mm: '03' -> invalid. Value does not fit in the `minute-interval`
// ss: '00' -> valid.
}
},
methods: {
errorHanlder (eventData) {
console.log(eventData)
// console.log outputs -> ["hour", "minute"]
}
}
```
The `error` event returns an _Array_ of invalid fields' names. When it returns an empty array `[]`, it means the current input is valid, and all previous errors are gone
> NOTE: Empty value will **not** be marked as invalid.
## Helper CSS Class Names
Started from `v.1.1.0+`, Vue Timepicker will add additional CSS classes to the `<input>` element base on the state of the current input value.
- **invalid**: One or more fields containing an invalid or disabled value.
- Additional CSS Style: The `<input>` border turns red.
- If you want to mute this red border style, add `"skip-error-style"` to `input-class`
- **is-empty**: The input value (_v-model_) is empty. No additional style.
- **all-selected**: All fields (hour/minute/second/apm) required by the `format` string are not empty. No additional style.
```html
<!-- To mute the red border style of "invalid" state -->
<timepicker input-class="skip-error-style"></timepicker>
<timepicker :input-class="['skip-error-style', 'your-other-class-names']"></timepicker>
```
## Miscellaneous Props API
Prop | Type | Required | Default Value
----------------------- | --------- | -------- | -------------
**hour-label** | _String_ | no | _undefined_
**minute-label** | _String_ | no | _undefined_
**second-label** | _String_ | no | _undefined_
**apm-label** | _String_ | no | _undefined_
**am-text** | _String_ | no | _undefined_
**pm-text** | _String_ | no | _undefined_
### Customized Picker Labels
You can define customized labels on top of the hour, minute, second, and APM pickers with the following properties: `hour-label`, `minute-label`, `second-label`, and `apm-label`.
Furthermore, you can replace those _am/pm_ (or _AM/PM_) string by setting the `am-text` and `pm-text` parameters.
> Please note that these two parameters only change the labels expose to the users (the UI level). The `v-model` value and `displayTime` value returned by the `change` event (the data level) still use the standard _am_/_pm_ (_AM_/_PM_) format.
```html
<!-- 24-hour format with customized hour and minute label -->
<vue-timepicker hour-label="heure" minute-label="minute"></vue-timepicker>
<!-- 12-hour format with customized am/pm text -->
<vue-timepicker hour-label="時" minute-label="分" second-label="秒" apm-label="午" am-text="上午" pm-text="下午" format="h:mm:ss a"></vue-timepicker>
```
## Slots
We introduce three slots in `v.1.1.4` to help you customize the clear button, the dropdown button, and the input icon with your own icon/image.
Slot Name | Position | Description
------------------ | -------- | --------------
**icon** | _left_ | On the lefthand side of the `<input>`
**clearButton** | _right_ | In the same spot of the default clear button
**dropdownButton** | _right_ | In the same spot of the default dropdown button
> Please note that Vue v2.6.0+ introduces a significant update of the Named Slots syntax. Check the [official documentation](https://vuejs.org/v2/guide/components-slots.html#Named-Slots) for more information.
```html
<!-- For Vue 2.6.0+ -->
<!-- Input icon (image) -->
<vue-timepicker>
<template v-slot:icon>
<img src="$YOUR_ICON_SRC" />
</template>
</vue-timepicker>
<!-- Customized clear button (image) -->
<vue-timepicker>
<template v-slot:clearButton>
<img src="$YOUR_CUSTOM_IMAGE_SRC" />
</template>
</vue-timepicker>
<!-- Customized dropdown button (character entity) -->
<vue-timepicker manual-input hide-dropdown>
<template v-slot:dropdownButton>≣</template>
</vue-timepicker>
```
## Contribution
Please feel free to fork and help developing. Check [CONTRIBUTING.md](https://github.com/phoenixwong/vue2-timepicker/blob/master/CONTRIBUTING.md) for more details.
## Change Log
Detail changes of each release: [CHANGELOG.md](https://github.com/phoenixwong/vue2-timepicker/blob/master/CHANGELOG.md)
## License
[MIT](https://github.com/phoenixwong/vue2-timepicker/blob/master/LICENSE.md)
================================================
FILE: babel.config.js
================================================
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
================================================
FILE: demo/.gitignore
================================================
.DS_Store
node_modules
/dist
yarn.lock*
package.lock*
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
================================================
FILE: demo/README.md
================================================
# Vue2 Timepicker Demo
## Project setup
```
yarn install
```
### Compiles and hot-reloads for development
```
yarn run serve
```
### Compiles and minifies for production
```
yarn run build
```
### Lints and fixes files
```
yarn run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
================================================
FILE: demo/babel.config.js
================================================
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
================================================
FILE: demo/package.json
================================================
{
"name": "vue2-timepicker-demo",
"version": "1.1.6",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.6.5",
"highlight.js": "^9.18.5",
"vue": "^2.6.11",
"vue-highlight.js": "^3.1.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.3.1",
"@vue/cli-plugin-eslint": "^4.3.1",
"@vue/cli-service": "^4.3.1",
"babel-eslint": "^10.1.0",
"eslint": "^6.8.0",
"eslint-plugin-vue": "^6.2.2",
"stylus": "^0.54.7",
"stylus-loader": "^3.0.2",
"vue-cli-plugin-pug": "^1.0.7",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": false,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"rules": {},
"parserOptions": {
"parser": "babel-eslint"
}
},
"postcss": {
"plugins": {
"autoprefixer": {}
}
},
"browserslist": [
"> 1%",
"last 2 versions"
]
}
================================================
FILE: demo/public/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, minimal-ui, maximum-scale=1.0, minimum-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>Vue2 Timepicker Demo</title>
</head>
<body>
<noscript>
<strong>We're sorry but vue2-timepicker-3 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
<a href="https://github.com/phoenixwong/vue2-timepicker" target="_blank"><img style="position: absolute; top: 0; left: 0; border: 0;" src="https://camo.githubusercontent.com/567c3a48d796e2fc06ea80409cc9dd82bf714434/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f6c6566745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_left_darkblue_121621.png"></a>
</body>
</html>
================================================
FILE: demo/src/App.vue
================================================
<script>
import Samples from './components/Samples'
import Playground from './components/Playground'
export default {
name: 'VueTimepickerDemo',
components: {
Samples,
Playground
},
data () {
return {
currentView: 'samples',
stickyNav: false,
scrollTop: 0
}
},
methods: {
switchView (target) {
try {
history.replaceState(null, null, ' ')
} catch (e) {
// Failsafe for outdated browsers. Do nothing here.
}
this.currentView = target
this.$nextTick(() => {
if (document.documentElement && document.documentElement.scrollTop) {
document.documentElement.scrollTop = 0
} else if (document.body.parentNode && document.body.parentNode.scrollTop) {
document.body.parentNode.scrollTop = 0
} else {
document.body.scrollTop = 0
}
})
},
scrollHandler (evt) {
this.scrollTop = (evt.target.scrollingElement || (document.documentElement || document.body.parentNode)).scrollTop || 0
if (this.scrollTop > 150) {
if (!this.stickyNav) {
this.stickyNav = true
}
} else {
if (this.stickyNav) {
this.stickyNav = false
}
}
}
},
mounted () {
window.addEventListener('scroll', this.scrollHandler)
},
beforeDestroy () {
window.removeEventListener('scroll', this.scrollHandler)
}
}
</script>
<template lang="pug">
#app.main-wrapper
header(v-cloak)
h1
| Vue
span.version 2
| Timepicker
nav.top-nav(:class="{stick: stickyNav}")
span.title
| Vue
i 2
| Timepicker
ul
li
a(:class="{active: currentView === 'samples'}" @click="switchView('samples')") Common Usage
li
a(:class="{active: currentView === 'playground'}" @click="switchView('playground')") Playground
li
a(href="https://github.com/phoenixwong/vue2-timepicker/blob/master/README.md" target="_blank") Documentation
span.version
a(href="https://www.npmjs.com/package/vue2-timepicker" target="_blank")
img(alt="NPM latest version" src="https://img.shields.io/npm/v/vue2-timepicker?style=flat-square")
span.downloads
a(href="https://www.npmjs.com/package/vue2-timepicker" target="_blank")
img(alt="NPM downloads" src="https://img.shields.io/npm/dm/vue2-timepicker?style=flat-square")
main.content(:class="{'nav-affixed': stickyNav}")
transition(name="fade" mode="out-in")
component(:is="currentView")
//- Footer
template(slot="footer-links")
h3.title
a#more.anchor #
| More complex usage
.description
p
| Didn't find what you need? Please check the
a(@click="switchView('playground')") Playground
| or
a(href="https://github.com/phoenixwong/vue2-timepicker/blob/master/README.md" target="_blank" title="Vue2-Timepicker Documentation") Documentation
| for more inspiration.
</template>
<style lang="stylus">
@import './assets/demo.styl';
</style>
================================================
FILE: demo/src/assets/_variables.styl
================================================
$vue-green = #41B883
$vue-green-light = lighten($vue-green, 5%)
$vue-dark = #35495E
$vue-darker = darken($vue-dark, 25%)
$body-color = #555
$dark-grey = #777
-black($alpha)
rgba(0, 0, 0, $alpha)
-white($alpha)
rgba(255, 255, 255, $alpha)
================================================
FILE: demo/src/assets/demo.styl
================================================
@import './_variables.styl'
body,
html
margin: 0
padding: 0
font-family: sans-serif
color: $body-color
-webkit-font-smoothing: antialiased
-moz-osx-font-smoothing: grayscale
body
font-size: 16px
h2,
h3,
h4
color: $vue-dark
h2
margin: 2em 0 1.5em 0
h3
margin: 0 0 1em 0
h4
margin-bottom: 0.5em
section
width: 80%
max-width: 1000px
margin: 0 auto 2em auto
a
color: $vue-green
text-decoration: none
header
background: $vue-darker
color: #fff
text-align: center
height: 150px
display: flex
flex-flow: column nowrap
justify-content: center
align-items: center
position: relative
h1
margin: 0
color: $vue-green-light
.version
font-weight: 300
margin: 0 .2em 0 .1em
p
margin-bottom: 0
color: -white(0.3)
font-size: 300
.version
font-weight: 100
background-color: alpha($vue-dark, 0.7)
padding: .1em .5em
border-radius: 3px
button
display: inline-block
outline: 0
background: $vue-green
border: 1px solid $vue-green
color: #fff
border-radius: 4px
font-size: 0.9em
vertical-align: baseline
padding: 0.3em 0.5em
transition: opacity 0.3s
cursor: pointer
&:hover
opacity: 0.7
button.common
background: #fff
border: 1px solid $vue-green
color: $vue-green
button.secondary
background: #fff
border: 1px solid $vue-darker
color: $vue-darker
button.size-small
font-size 0.8em;
padding: 0.2em 0.4em;
nav.top-nav
background: $vue-darker
position: relative
.title
display: none
span.version,
span.downloads
a
border: 0
text-decoration: none
span.version
position: absolute
z-index: 301
right: 1em
bottom: .5em
span.downloads
position: absolute
z-index: 301
left: .8em
bottom: .5em
&.stick
position: fixed
top: 0
left: 0
right: 0
z-index: 300
.title
display: inline-block
color: -white(0.7)
position: absolute
z-index: 301
left: 1em
top: .8em
span.downloads
display: none
ul
list-style: none
padding: 0
margin: 0
display: flex
flex-flow: row nowrap
justify-content: center
align-items: stretch
li
margin: 0 1em
overflow: hidden
a
color: -white(0.5)
display: block
padding: .8em .5em
border-radius: 5px
-webkit-transition: color .3s
transition: color .3s
position: relative
overflow: hidden
z-index: 1
&:hover
color: alpha($vue-green, 0.7)
cursor: pointer
&.active
color: $vue-green-light
&:after
content: ''
display: block
width: 0
height: 0
border: 10px solid transparent
border-bottom-color: #fff
position: absolute
bottom: -3px
left: calc(50% - 10px)
z-index: 3
main.content
&.nav-affixed
padding-top: 44px
.fade
transition: opacity .5s ease
.fade-enter-active, .fade-leave-active
opacity: 0
.description
p
line-height: 1.5em
code
color: $vue-dark
background: -black(0.03)
border-radius: 3px
padding: 0.2em 0.5em
margin: 0 0.2em
vertical-align: baseline
.preview
padding: 2em 1.5em
border: 1px solid -black(0.07)
border-radius: 3px
b
font-size: 0.9em
color: $dark-grey
p
margin: 0
padding: .5em 0 1.5em 0
&:last-of-type
padding-bottom: 0
.codes
pre
position: relative
font-size: 0.8em
code
padding: 2em
border-radius: 3px
&:after
content: attr(data-title)
position: absolute
top: 0.3em
right: 0.8em
font-size: 0.8em
color: alpha($vue-dark, 0.6)
.capitailized
text-transform: uppercase
================================================
FILE: demo/src/components/ConfigRow.vue
================================================
<script>
export default {
name: 'ConfigRow',
props: {
label: { type: String },
isGroup: { type: Boolean, default: false }
}
}
</script>
<template lang="pug">
.config-row(:class="{'group': isGroup }")
label.row-label(v-if="this.label && this.label.length") {{ label }}
slot
</template>
<style lang="stylus">
.config-row
padding: 0.5em 0
display: flex
flex-flow: row wrap
justify-content: flex-start
align-items: center
align-content: flex-start
.row-label
display: inline-block
font-weight: bold
width: 5em
text-align: right
margin-right: 0.5em
label.options
min-width: 3em
margin-right: 0.5em
display: inline-flex
flex-flow: row wrap
justify-content: flex-start
align-items: center
position: relative
input[type=radio],
input[type=checkbox]
position: relative
top: -0.1em
.range-wrapper
display: inline-flex
flex-flow: row nowrap
justify-content: flex-start
align-items: center
input[type=range]
margin-right: 0.8em
&.group
padding-left: 1em
display: flex
flex-flow: row wrap
justify-content: flex-start
align-items: center
</style>
================================================
FILE: demo/src/components/OverlayPanel.vue
================================================
<script>
export default {
name: 'OverlayPanel',
props: {
title: { type: String }
},
methods: {
closePanel () {
this.$emit('close')
}
}
}
</script>
<template lang="pug">
.overlay-panel(@click="closePanel")
.panel-body(@click.stop="")
.panel-title
.title-text(v-if="title" v-text="title")
.close-btn(@click="closePanel") ×
.panel-content
slot
.panel-footer
.footer-left
slot(name="footerLeft")
.footer-right
slot(name="footerRight")
</template>
<style lang="stylus">
@import '../assets/_variables.styl'
.overlay-panel
position: fixed
top: 0
left: 0
bottom: 0
right: 0
background: -black(0.7)
z-index: 5000
display: flex
flex-flow: column nowrap
justify-content: center
align-items: center
.panel-body
width: 500px
max-width: 80vw
max-height: 70vh
min-height: 200px
background: #fff
border-radius: 6px
box-shadow: 0 .1em 0.5em -black(0.35)
display: flex
flex-flow: column nowrap
justify-content: flex-start
align-items: stretch
.panel-title
display: flex
flex-flow: row nowrap
justify-content: flex-end
align-items: center
padding: 0.6em 0.8em 0.5em 0.8em
border-bottom: 1px solid -black(0.1)
.title-text
flex: 1 1 0.00001px
color: $vue-dark
line-height: 120%
font-weight: bold
font-size: 1.2em
.close-btn
margin-left: 1em
font-size: 1.2em
line-height: 100%
position: relative
top: -.2em
cursor: pointer
transition: opacity .3s
&:hover
opacity: 0.4
.panel-content
flex: 1 1 0.00001px
padding: 1em 0.8em
.panel-footer
border-top: 1px solid -black(0.1)
padding: 0.5em 0.6em 0.5em 0.8em
display: flex
flex-flow: row nowrap
justify-content: flex-start
align-items: center
.footer-left
flex: 1 1 0.00001px
button:not(:first-of-type)
margin-left: 0.6em
</style>
================================================
FILE: demo/src/components/Playground.vue
================================================
<script>
import VueTimepicker from '../../../src/vue-timepicker'
import ConfigRow from './ConfigRow'
import OverlayPanel from './OverlayPanel'
export default {
name: 'Playground',
components: {
VueTimepicker,
ConfigRow,
OverlayPanel
},
data () {
return {
tokens: {
hour: ['HH', 'H', 'hh', 'h', 'kk', 'k'],
minute: ['mm', 'm'],
second: ['ss', 's', 'none'],
apm: ['A', 'a']
},
type: {
hour: 'hh',
minute: 'mm',
second: 'ss',
apm: 'A'
},
selected: {
hour: 1,
minute: 0,
second: 0,
apm: 'am'
},
hourBoundary: {
min: 1,
max: 12
},
interval: {
minute: 1,
second: 1
},
customInterval: {
minute: false,
second: false
},
customRange: {
hour: false,
minute: false,
second: false
},
showRangePanel: false,
rangeList: undefined,
editingRange: '',
selectedRanges: [],
rangeTitle: '',
hourRange: [],
minuteRange: [],
secondRange: [],
hideClearBtn: false,
disablePicker: false,
closeOnComplete: false,
advancedKeyboard: false,
manualInput: false,
hideDropdown: false,
fixedDropdownBtn: false,
lazyMode: false,
autoScroll: false,
skipErrorStyle: false,
appendToBody: false,
debugMode: false,
customBlurDelay: false,
blurDelay: 300,
customManualInputTimeout: false,
manualInputTimeout: 1000,
playgroundData: {},
playgroundFullValue: {},
playgroundErroredData: undefined,
scrollTop: 0,
muteChange: false
}
},
computed: {
formatString () {
let formatString = `${this.type.hour}:${this.type.minute}`
if (this.showSeconds) {
formatString += (`:${this.type.second}`)
}
if (this.type.apm) {
formatString += (` ${this.type.apm}`)
}
return formatString
},
needApm () {
return this.type.hour === 'h' || this.type.hour === 'hh'
},
showSeconds () {
return this.type.second !== 'none'
},
yourTimeValue () {
let code = 'yourTimeValue: {\n'
code += this.listTimeValue()
code += '\n}'
return code
},
asideStyle () {
const initPaddingTop = 220
const minPaddingTop = 50
return {
paddingTop: (Math.max(initPaddingTop - this.scrollTop, minPaddingTop)) + 'px'
}
},
filteredOutValues () {
if (!this.showRangePanel || !this.rangeList || !this.selectedRanges.length) { return }
const result = []
this.selectedRanges.forEach(selected => {
if (selected && !this.rangeList.includes(selected)) {
result.push(selected)
}
})
return result
},
toHideDropdown () {
if (!this.manualInput) { return false }
return this.hideDropdown
},
showErroredData () {
return Boolean(this.playgroundErroredData && this.playgroundErroredData.length)
},
htmlCodeWithVar () {
let start = '<vue-timepicker'
let end = '\n v-model="yourTimeValue">\n</vue-timepicker>'
start += (`\n format="${this.formatString}"`)
if (this.skipErrorStyle) {
start += ('\n input-class="skip-error-style"')
}
if (this.customInterval.minute) {
start += (`\n :minute-interval="${this.interval.minute}"`)
}
if (this.showSeconds && this.customInterval.second) {
start += (`\n :second-interval="${this.interval.second}"`)
}
if (this.customRange.hour && this.hourRange) {
const hrRange = this.sortAndStringify(this.hourRange, this.needApm)
start += (`\n :hour-range="${hrRange}"`)
}
if (this.customRange.minute && this.minuteRange) {
const minRange = this.sortAndStringify(this.minuteRange)
start += (`\n :minute-range="${minRange}"`)
}
if (this.showSeconds && this.customRange.second && this.secondRange) {
const secRange = this.sortAndStringify(this.secondRange)
start += (`\n :second-range="${secRange}"`)
}
if (this.customBlurDelay) {
start += (`\n :blur-delay="${this.blurDelay}"`)
}
if (this.customManualInputTimeout) {
start += (`\n :manual-input-timeout="${this.manualInputTimeout}"`)
}
if (this.lazyMode) {
start += ('\n lazy')
}
if (this.closeOnComplete) {
start += ('\n close-on-complete')
}
if (this.manualInput) {
start += ('\n manual-input')
}
if (this.toHideDropdown) {
start += ('\n hide-dropdown')
}
if (this.advancedKeyboard) {
start += ('\n advanced-keyboard')
}
if (this.fixedDropdownBtn) {
start += ('\n fixed-dropdown-button')
}
if (this.hideClearBtn) {
start += ('\n hide-clear-button')
}
if (this.autoScroll) {
start += ('\n auto-scroll')
}
if (this.appendToBody) {
start += ('\n append-to-body')
}
if (this.disablePicker) {
start += ('\n disabled')
}
if (this.debugMode) {
start += ('\n debug-mode')
}
const htmlCode = start + end
return htmlCode
}
},
watch: {
selected: {
deep: true,
handler () {
this.updatePlaygroundData()
}
},
type: {
deep: true,
handler () {
this.updatePlaygroundData()
}
},
'type.hour' (newType, oldType) {
if (this.customRange.hour && this.hourRange.length) {
const newRangeList = this.hourRange.map(item => {
return this.transformHourRange(item, oldType, newType)
})
this.hourRange = newRangeList
}
},
'type.minute' (newType) {
if (this.customRange.minute && this.minuteRange.length) {
const newRangeList = this.minuteRange.map(item => {
return this.formatValue(newType, +item)
})
this.minuteRange = newRangeList
}
},
'type.second' (newType) {
if (newType !== 'none' && this.customRange.second && this.secondRange.length) {
const newRangeList = this.secondRange.map(item => {
return this.formatValue(newType, +item)
})
this.secondRange = newRangeList
}
},
needApm (isNeeded) {
if (isNeeded) {
if (!this.selected.apm) {
this.$set(this.type, 'apm', 'A')
this.$set(this.selected, 'apm', 'am')
}
} else {
this.$set(this.type, 'apm', '')
this.$set(this.selected, 'apm', '')
}
},
customInterval: {
deep: true,
handler (custom) {
if (!custom.minute) {
this.$set(this.interval, 'minute', 1)
}
if (!custom.second) {
this.$set(this.interval, 'second', 1)
}
}
}
},
methods: {
updateHourRange (hourType) {
hourType = hourType || this.type.hour
let hourBoundary = {}
switch (hourType) {
case 'h':
case 'hh':
hourBoundary.min = 1
hourBoundary.max = 12
break
case 'H':
case 'HH':
hourBoundary.min = 0
hourBoundary.max = 23
break
case 'k':
case 'kk':
hourBoundary.min = 1
hourBoundary.max = 24
break
}
this.hourBoundary = hourBoundary
this.handleOutRangeData()
},
handleOutRangeData () {
if (this.selected.hour > this.hourBoundary.max) {
this.$set(this.selected, 'hour', this.hourBoundary.max)
} else if (this.selected.hour < this.hourBoundary.min) {
this.$set(this.selected, 'hour', this.hourBoundary.min)
}
},
isNumber (value) {
return !isNaN(parseFloat(value)) && isFinite(value)
},
formatValue (type, value) {
switch (type) {
case 'H':
case 'h':
case 'k':
case 'm':
case 's':
if (type === 'h' && value === 0) {
return '12'
}
return String(value)
case 'HH':
case 'hh':
case 'kk':
case 'mm':
case 'ss':
if (type === 'hh' && value === 0) {
return '12'
}
return value < 10 ? `0${value}` : String(value)
default:
return ''
}
},
translate12hRange (value) {
const valueT = value.match(/^(\d{1,2})(a|p|A|P)$/)
if (+valueT[1] === 12) {
return +valueT[1] + (valueT[2].toLowerCase() === 'p' ? 0 : 12)
}
return +valueT[1] + (valueT[2].toLowerCase() === 'p' ? 12 : 0)
},
interpretKtoRangeType (kValue, toType) {
if (!toType || toType === 'k') { return String(kValue) }
let value
switch (toType) {
case 'H':
case 'HH':
value = (kValue === 24) ? 0 : kValue
if (toType === 'HH') {
return value < 10 ? `0${value}` : String(value)
}
return String(value)
case 'h':
case 'hh':
if (kValue === 24) {
return `12a`
} else if (kValue === 12) {
return `12p`
}
value = kValue % 12
if (toType === 'hh') {
const valueStr = value < 10 ? `0${value}` : String(value)
return kValue < 12 ? `${valueStr}a` : `${valueStr}p`
}
return kValue < 12 ? `${value}a` : `${value}p`
case 'kk':
return kValue < 10 ? `0${kValue}` : String(kValue)
}
},
transformHourRange (value, fromType, toType) {
if (!fromType || !toType) { return value }
let valueInK
if (fromType === 'hh' || fromType === 'h') {
valueInK = this.translate12hRange(value)
} else if (fromType === 'HH' || fromType === 'H') {
valueInK = +value === 0 ? 24 : +value
} else {
valueInK = +value
}
return this.interpretKtoRangeType(valueInK, toType)
},
updatePlaygroundData () {
let data = {}
if (this.isNumber(this.selected.hour)) {
data[this.type.hour] = this.formatValue(this.type.hour, this.selected.hour)
} else {
data[this.type.hour] = ''
}
if (this.isNumber(this.selected.minute)) {
data[this.type.minute] = this.formatValue(this.type.minute, this.selected.minute)
} else {
data[this.type.minute] = ''
}
if (this.showSeconds) {
if (this.isNumber(this.selected.second)) {
data[this.type.second] = this.formatValue(this.type.second, this.selected.second)
} else {
data[this.type.second] = ''
}
}
if (this.type.apm) {
if (this.selected.apm) {
data[this.type.apm] = this.type.apm === 'A' ? (this.selected.apm).toUpperCase() : this.selected.apm
} else {
data[this.type.apm] = ''
}
}
this.playgroundData = data
},
listTimeValue () {
const data = this.playgroundData
const len = Object.keys(data).length
let string = ''
Object.keys(data).forEach((k, i) => {
string += ` ${k}: "${data[k]}"`
if (i < len - 1) {
string += '\n'
}
})
return string
},
updateRangeValue (data) {
this.muteChange = true
this.$set(this.selected, 'hour', this.isNumber(data[this.type.hour]) ? Number(data[this.type.hour]) : '')
this.$set(this.selected, 'minute', this.isNumber(data[this.type.minute]) ? Number(data[this.type.minute]) : '')
this.$set(this.selected, 'second', this.isNumber(data[this.type.second]) ? Number(data[this.type.second]) : '')
this.$set(this.selected, 'apm', data[this.type.apm] ? (data[this.type.apm] || '').toLowerCase() : '')
this.muteChange = false
},
changeHandler (eventData) {
this.playgroundFullValue = eventData
this.updateRangeValue(eventData.data)
},
errorHandler (eventData) {
this.playgroundErroredData = eventData
},
scrollHandler (evt) {
this.scrollTop = (evt.target.scrollingElement || (document.documentElement || document.body.parentNode)).scrollTop || 0
},
sortAndStringify (arrayList, is12Hour) {
if (!arrayList || !arrayList.length) { return JSON.stringify([]) }
let newList = [].concat([], arrayList)
if (is12Hour) {
newList.sort((l, r) => {
const lPart = l.match(/^(\d{1,2})(a|p)$/)
const rPart = r.match(/^(\d{1,2})(a|p)$/)
const lApm = lPart[2]
const rApm = rPart[2]
if (lApm === 'a' && rApm === 'p') { return -1 }
if (lApm === 'p' && rApm === 'a') { return 1 }
const lNum = +lPart[1]
const rNum = +rPart[1]
if (lNum === 12) { return -1 }
if (rNum === 12) { return 1 }
return lNum < rNum ? -1 : 1
})
const uniStrList = newList.map(item => {
const itemP = item.match(/^(\d{1,2})(a|p)$/)
return `${+itemP[1]}${itemP[2]}`
})
return JSON.stringify(uniStrList).replace(/"/g, '\'')
} else {
newList.sort((l, r) => (+l < +r) ? -1 : 1)
const numericList = newList.map(item => +item)
return JSON.stringify(numericList).replace(/"/g, '')
}
},
genHourRangeList () {
const result = []
for (let i = 0; i < 24; i++) {
// 12-Hour format
if (this.type.hour === 'h' || this.type.hour === 'hh') {
let value = this.formatValue(this.type.hour, i % 12)
value = `${value}${i < 12 ? 'a' : 'p'}`
result.push(value)
} else {
if (this.type.hour === 'k' || this.type.hour === 'kk') {
result.push(this.formatValue(this.type.hour, i + 1))
} else {
result.push(this.formatValue(this.type.hour, i))
}
}
}
return result
},
genMinuteRangeList () {
const result = []
const step = +this.interval.minute
for (let i = 0; i <= 59; i += step) {
result.push(this.formatValue(this.type.minute, i))
}
return result
},
genSecondRangeList () {
const result = []
const step = +this.interval.second
for (let i = 0; i <= 59; i += step) {
result.push(this.formatValue(this.type.second, i))
}
return result
},
openRangePanel (section) {
if (!section) { return }
this.rangeTitle = `Choose ${section}-range Values`
this.editingRange = section
if (section === 'minute') {
this.rangeList = this.genMinuteRangeList()
this.selectedRanges = [].concat([], this.minuteRange)
} else if (section === 'second') {
this.rangeList = this.genSecondRangeList()
this.selectedRanges = [].concat([], this.secondRange)
} else if (section === 'hour') {
this.rangeList = this.genHourRangeList()
this.selectedRanges = [].concat([], this.hourRange)
}
this.showRangePanel = true
},
confirmRange () {
if (this.editingRange === 'minute') {
this.minuteRange = [].concat([], this.selectedRanges || [])
} else if (this.editingRange === 'second') {
this.secondRange = [].concat([], this.selectedRanges || [])
} else if (this.editingRange === 'hour') {
this.hourRange = [].concat([], this.selectedRanges || [])
}
this.$nextTick(() => {
this.closeRangePanel()
})
},
closeRangePanel () {
this.rangeTitle = ''
this.editingRange = ''
this.rangeList = undefined
this.selectedRanges = []
this.showRangePanel = false
},
selectAllRangeItems () {
this.selectedRanges = [].concat([], this.rangeList || [])
},
unselectAllRangeItems () {
this.selectedRanges = []
},
toggleBlurDelay () {
this.blurDelay = 300
},
toggleManualInputTimeout () {
this.manualInputTimeout = 1000
}
},
mounted () {
window.addEventListener('scroll', this.scrollHandler)
this.$nextTick(() => {
this.updateHourRange()
this.updatePlaygroundData()
})
},
beforeDestroy () {
window.removeEventListener('scroll', this.scrollHandler)
}
}
</script>
<template lang="pug">
section#playground
main
h2.section-title Timepicker Playground
#configPanel
#typesSelection.config-block
h3.subtitle
a.anchor #
| Generate
code format
| string
config-row(label="Hour:")
label.options(v-for="(htype, index) in tokens.hour", :key="index", :for="'hour_type' + index" @mouseup.stop="updateHourRange(htype)")
input(v-model="type.hour", :value="htype", :id="'hour_type' + index" type="radio" name="hour_type")
| {{ htype }}
config-row(label="Minute:")
label.options(v-for="(mtype, index) in tokens.minute", :key="index", :for="'minute_type' + index")
input(v-model="type.minute", :value="mtype", :id="'minute_type' + index" type="radio" name="minute_type")
| {{ mtype }}
config-row(label="Second:")
label.options(v-for="(stype, index) in tokens.second", :key="index", :for="'second_type' + index")
input(v-model="type.second", :value="stype", :id="'second_type' + index" type="radio" name="second_type")
| {{ stype }}
config-row(v-if="needApm" label="AM/PM:")
label.options(v-for="(atype, index) in tokens.apm", :key="index", :for="'apm_type' + index")
input(v-model="type.apm", :value="atype", :id="'apm_type' + index" type="radio" name="apm_type")
| {{ atype }}
#valuesSelection.config-block
h3.subtitle
a.anchor #
| Set
code v-model
| data
config-row(label="Hour:")
label.range-wrapper
input(v-model="selected.hour" type="range", :min="hourBoundary.min", :max="hourBoundary.max" step="1")
span(v-text="selected.hour")
config-row(label="Minute:")
label.range-wrapper
input(v-model="selected.minute" type="range" min="0" max="59", :step="interval.minute")
span(v-text="selected.minute")
config-row(v-if="showSeconds" label="Second:")
label.range-wrapper
input(v-model="selected.second" type="range" min="0" max="59", :step="interval.second")
span(v-text="selected.second")
config-row(v-if="needApm" label="AM/PM:", :class="{'capitailized': type.apm === 'A'}")
label.options(for="selected_apm_am")
input(v-model="selected.apm" type="radio" id="selected_apm_am" name="selected_apm" value="am")
| am
label.options(for="selected_apm_pm")
input(v-model="selected.apm" type="radio" id="selected_apm_pm" name="selected_apm" value="pm")
| pm
.codes
highlight-code(lang="javascript" data-title="v-model value") {{ yourTimeValue }}
#intervalSelection.config-block
h3.subtitle
a.anchor #
| Customized Intervals
config-row(is-group)
label.options
input(v-model="customInterval.minute" type="checkbox")
| Set Minute Interval
label.range-wrapper(v-if="customInterval.minute")
input(v-model.number="interval.minute" type="range" min="0" max="60" step="1")
span(v-text="interval.minute")
config-row(is-group v-if="showSeconds")
label.options
input(v-model="customInterval.second" type="checkbox")
| Set Second Interval
label.range-wrapper(v-if="customInterval.second")
input(v-model.number="interval.second" type="range" min="0" max="60" step="1")
span(v-text="interval.second")
#customRanges.config-block
h3.subtitle
a.anchor #
| Customized Ranges
config-row(is-group)
label.options
input(v-model="customRange.hour" type="checkbox")
| Set Hour Range
.button-wrapper(v-if="customRange.hour" )
button.common.size-small(@click="openRangePanel('hour')") Config
span.item-count {{ hourRange.length }} value{{hourRange.length > 1 ? 's' : ''}} selected
config-row(is-group)
label.options
input(v-model="customRange.minute" type="checkbox")
| Set Minute Range
.button-wrapper(v-if="customRange.minute" )
button.common.size-small(@click="openRangePanel('minute')") Config
span.item-count {{ minuteRange.length }} value{{minuteRange.length > 1 ? 's' : ''}} selected
config-row(is-group v-if="showSeconds")
label.options
input(v-model="customRange.second" type="checkbox")
| Set Second Range
.button-wrapper(v-if="customRange.second" )
button.common.size-small(@click="openRangePanel('second')") Config
span.item-count {{ secondRange.length }} value{{secondRange.length > 1 ? 's' : ''}} selected
#closeOnComplete.config-block
h3.subtitle
a.anchor #
| Close on Complete
config-row(is-group)
label.options(for="close_on_complete_true")
input(v-model="closeOnComplete" type="radio" id="close_on_complete_true" name="close_on_complete", :value="true")
| Enable
label.options(for="close_on_complete_false")
input(v-model="closeOnComplete" type="radio" id="close_on_complete_false" name="close_on_complete", :value="false")
| Disable
#clearButton.config-block
h3.subtitle
a.anchor #
| Clear Button
config-row(is-group)
label.options(for="hide_clear_btn_false")
input(v-model="hideClearBtn" type="radio" id="hide_clear_btn_false" name="hide_clear_btn", :value="false")
| Enable
label.options(for="hide_clear_btn_true")
input(v-model="hideClearBtn" type="radio" id="hide_clear_btn_true" name="hide_clear_btn", :value="true")
| Disable
#disablePicker.config-block
h3.subtitle
a.anchor #
| Disable Picker
config-row(is-group)
label.options
input(v-model="disablePicker" type="checkbox")
| Disable
#lazyMode.config-block
h3.subtitle
a.anchor #
| Lazy Event Mode
config-row(is-group)
label.options(for="lazy_mode_true")
input(v-model="lazyMode" type="radio" id="lazy_mode_true" name="lazy_mode", :value="true")
| Enable
label.options(for="lazy_mode_false")
input(v-model="lazyMode" type="radio" id="lazy_mode_false" name="lazy_mode", :value="false")
| Disable
#autoScroll.config-block
h3.subtitle
a.anchor #
| Auto Scroll
config-row(is-group)
label.options(for="auto_scroll_true")
input(v-model="autoScroll" type="radio" id="auto_scroll_true" name="auto_scroll", :value="true")
| Enable
label.options(for="auto_scroll_false")
input(v-model="autoScroll" type="radio" id="auto_scroll_false" name="auto_scroll", :value="false")
| Disable
#manualInput.config-block
h3.subtitle
a.anchor #
| Manually Input Support
config-row(is-group)
label.options(for="manual_input_true")
input(v-model="manualInput" type="radio" id="manual_input_true" name="manual_input", :value="true")
| Enable
label.options(for="manual_input_false")
input(v-model="manualInput" type="radio" id="manual_input_false" name="manual_input", :value="false")
| Disable
#hideDropdown.config-block(v-if="manualInput")
h3.subtitle
a.anchor #
| Hide Dropdown
config-row(is-group)
label.options(for="hide_dropdown_true")
input(v-model="hideDropdown" type="radio" id="hide_dropdown_true" name="hide_dropdown", :value="true")
| Enable
label.options(for="hide_dropdown_false")
input(v-model="hideDropdown" type="radio" id="hide_dropdown_false" name="hide_dropdown", :value="false")
| Disable
#manualInputTimeout.config-block(v-if="manualInput")
h3.subtitle
a.anchor #
| Customized Manual Input Timeout
config-row(is-group)
label.options
input(v-model="customManualInputTimeout" type="checkbox" @input="toggleManualInputTimeout")
| Set Manual Input Timeout
label.range-wrapper(v-if="customManualInputTimeout")
input(v-model.number="manualInputTimeout" type="range" min="50" max="5000" step="50")
span(v-text="manualInputTimeout")
#advancedKeyboard.config-block
h3.subtitle
a.anchor #
| Advanced Keyboard Support
config-row(is-group)
label.options(for="advanced_kb_true")
input(v-model="advancedKeyboard" type="radio" id="advanced_kb_true" name="advanced_kb", :value="true")
| Enable
label.options(for="advanced_kb_false")
input(v-model="advancedKeyboard" type="radio" id="advanced_kb_false" name="advanced_kb", :value="false")
| Disable
#blurDelay.config-block
h3.subtitle
a.anchor #
| Customized Blur Delay
config-row(is-group)
label.options
input(v-model="customBlurDelay" type="checkbox" @input="toggleBlurDelay")
| Set Blur Delay
label.range-wrapper(v-if="customBlurDelay")
input(v-model.number="blurDelay" type="range" min="50" max="1500" step="50")
span(v-text="blurDelay")
#fixedDropdownBtn.config-block
h3.subtitle
a.anchor #
| Fixed Dropdown Button
config-row(is-group)
label.options(for="fixed_dd_btn_true")
input(v-model="fixedDropdownBtn" type="radio" id="fixed_dd_btn_true" name="fixed_dd_btn", :value="true")
| Enable
label.options(for="fixed_dd_btn_false")
input(v-model="fixedDropdownBtn" type="radio" id="fixed_dd_btn_false" name="fixed_dd_btn", :value="false")
| Disable
#skipErrorStyle.config-block
h3.subtitle
a.anchor #
| Skip Error Style
config-row(is-group)
label.options(for="skip_error_true")
input(v-model="skipErrorStyle" type="radio" id="skip_error_true" name="skip_error", :value="true")
| Enable
label.options(for="skip_error_false")
input(v-model="skipErrorStyle" type="radio" id="skip_error_false" name="skip_error", :value="false")
| Disable
#appendToBody.config-block
h3.subtitle
a.anchor #
| Append To Body
config-row(is-group)
label.options(for="append_to_body_true")
input(v-model="appendToBody" type="radio" id="append_to_body_true" name="append_to_body", :value="true")
| Enable
label.options(for="append_to_body_false")
input(v-model="appendToBody" type="radio" id="append_to_body_false" name="append_to_body", :value="false")
| Disable
#debugMode.config-block
h3.subtitle
a.anchor #
| Debug Mode
config-row(is-group)
label.options(for="debug_mode_true")
input(v-model="debugMode" type="radio" id="debug_mode_true" name="debug_mode", :value="true")
| Enable
label.options(for="debug_mode_false")
input(v-model="debugMode" type="radio" id="debug_mode_false" name="debug_mode", :value="false")
| Disable
//-
//- Live preview on the left panel
//-
aside.previews(:style="asideStyle")
#playgroundPreview.preview
label(for="vueTimepickerInPlayground")
b Format string:
span(v-text="formatString")
p
vue-timepicker(v-model="playgroundData"
id="vueTimepickerInPlayground"
:format="formatString"
:minute-interval="interval.minute"
:second-interval="showSeconds ? interval.second : null"
:hour-range="customRange.hour ? hourRange : null"
:minute-range="customRange.minute ? minuteRange : null"
:second-range="(showSeconds && customRange.second) ? secondRange : null"
:close-on-complete="closeOnComplete"
:advanced-keyboard="advancedKeyboard"
:manual-input="manualInput"
:hide-dropdown="toHideDropdown"
:blur-delay="blurDelay"
:manual-input-timeout="manualInputTimeout"
:hide-clear-button="hideClearBtn"
:fixed-dropdown-button="fixedDropdownBtn"
:disabled="disablePicker"
:lazy="lazyMode"
:auto-scroll="autoScroll"
:append-to-body="appendToBody"
:debug-mode="debugMode"
:input-class="skipErrorStyle ? 'skip-error-style' : null"
@change="changeHandler"
@error="errorHandler")
#htmlCodePreview.codes
highlight-code(lang="html" data-title="HTML") {{ htmlCodeWithVar }}
#dispatchedValue.codes
highlight-code(lang="json" data-title="@change event data") {{ playgroundFullValue }}
highlight-code(v-if="showErroredData" lang="json" data-title="@error event data") {{ playgroundErroredData }}
//-
//- Customized Range Panels
//-
overlay-panel(v-if="showRangePanel" :title="rangeTitle" @close="closeRangePanel")
template(v-slot:footerLeft)
button.secondary(@click="selectAllRangeItems") Select All
button.secondary(@click="unselectAllRangeItems") Unselect All
template(v-slot:footerRight)
button(@click="confirmRange") Confirm
.valid-items
label.range-item(v-for="(rangeItem, rIndex) in rangeList")
input(type="checkbox" name="selected_ranges" v-model="selectedRanges" :value="rangeItem")
| {{ rangeItem }}
.invalid-items(v-if="filteredOutValues && filteredOutValues.length")
b Values selected but filtered out by the
template(v-if="editingRange !== 'hour'") {{editingRange}}-interval:
template(v-else) current hour type
.items-list
span.invalid-range(v-for="oItem in filteredOutValues" :key="oItem" v-text="oItem")
</template>
<style lang="stylus">
@import '../assets/_variables.styl'
section#playground
main
padding-left: 420px
.codes
pre,
code
overflow-x: auto
.config-block
.subtitle
margin: 0
padding: 1em 0 0.5em 0
position: relative
a.anchor
position: absolute
left: -1em
&:first-of-type
.subtitle
padding-top: 0
.button-wrapper
display: flex
flex-flow: row wrap
justify-content: flex-start
align-items: center
padding: 0.3em 0.5em
border-radius: 4px
background: -black(0.05)
aside.previews
position: fixed
width: 320px
left:10%
top: 0
z-index: 10
padding-top: 220px
#playgroundPreview
box-sizing: border-box
background: #fff
padding: 1em 1.5em
.range-item,
.invalid-range
display: inline-block
margin-right: 1em
margin-bottom: 0.5em
.range-item
min-width: 3em
.invalid-range
opacity: 0.7
.invalid-items
margin-top: 1em
padding: 0.8em 0.8em 0.3em 0.8em
background: -black(0.05)
border-radius: 6px
.items-list
padding-top: 0.8em
.item-count
font-size: 0.85em
padding-left: 0.5em
opacity: 0.7
</style>
================================================
FILE: demo/src/components/SampleBlock.vue
================================================
<script>
export default {
name: 'SampleBlock',
props: {
id: { type: String }
},
computed: {
blockHerf () {
if (this.id && this.id.length) {
return `#${this.id}`
}
return null
}
}
}
</script>
<template lang="pug">
.sample-block(:id="id")
h3.title
a.anchor(:href="blockHerf") #
slot(name="title")
.description
slot(name="description")
.codes
slot(name="codes")
.preview
slot(name="preview")
.codes(v-if="$slots.data")
slot(name="data")
</template>
<style lang="stylus">
.sample-block
padding: 5em 0 0 20%
&:first-of-type
padding-top: 0
.title
position: relative
margin-bottom: 1.5em
a.anchor
position: absolute
left: -1em
.description,
.preview,
.codes
margin-left: 1.5em
.inline-data-preview
display: inline-block
margin-left: 1em
font-size: 0.9em
ul
margin: 0 0 1em 0
padding: 0 0 0 1.2em
li
list-style: circle
line-height: 150%
</style>
================================================
FILE: demo/src/components/Samples.vue
================================================
<script>
import VueTimepicker from '../../../src/vue-timepicker'
import SampleBlock from './SampleBlock'
export default {
name: 'Samples',
components: {
VueTimepicker,
SampleBlock
},
data () {
return {
yourData: {
hh: '03',
mm: '05',
ss: '00',
a: 'am'
},
yourFormat: 'hh:mm:ss a',
yourDaysArray: [
{start_time: {HH: '08', mm: '00'}, end_time: {HH: '09', mm: '00'}},
{start_time: {HH: '15', mm: '00'}, end_time: {HH: '', mm: ''}},
{start_time: {HH: '', mm: ''}, end_time: {HH: '13', mm: '30'}},
{start_time: {HH: '', mm: ''}, end_time: {HH: '', mm: ''}}
],
simpleStringValue: '02:30',
yourStringValue: '3:mm:05 A',
unsetStringValue: '',
muteFlowListener: true,
latestDataFlow: undefined,
demoData1: {HH: '08', mm: '30'},
demoData2: {HH: '10', mm: '45'},
demoArgs: undefined,
dropdownStatus: 'closed',
focusState: 'blurred',
dropdownState: 'closed',
lazyData: {
hh: '06',
mm: '50',
ss: '00',
a: 'am'
},
lazyChangeData: undefined,
lazyInputData: undefined,
lazyEventTs: undefined,
manualStringValue: '8:15 pm',
customCloseBtnValue: '10:05',
autoScrollData1: '08:40',
autoScrollData2: '5:30:20 pm',
apmFirst1: 'AM 03:15',
apmFirst2: 'pm9時6分',
sideNav: [
{ title: 'Default', anchor: 'default' },
{ title: '12 Hours', anchor: 'format12hours' },
{ title: 'Seconds Picker', anchor: 'seconds' },
{ title: 'Customized Interval', anchor: 'interval' },
{ title: 'Using v-model', anchor: 'vModel' },
{ title: 'v-model with String Value', anchor: 'vModelWithString' },
{ title: 'Work with v-for', anchor: 'vForSample' },
{ title: 'Hour Range', anchor: 'hourRange' },
{ title: 'Minute and Second Range', anchor: 'minuteAndSecondRange' },
{ title: 'Hide Disabled Items', anchor: 'hideDisabledItems' },
{ title: 'Close on Complete', anchor: 'closeOnComplete' },
{ title: 'Hide Clear Button', anchor: 'hideClearButton' },
{ title: 'Disable Picker', anchor: 'disablePicker' },
{ title: 'The @change Event', anchor: 'onChangeSample' },
{ title: 'Lazy Event Mode', anchor: 'lazyEvents' },
{ title: 'Keyboard Support', anchor: 'kbSupport' },
{ title: 'Manual Input', anchor: 'manualInput'},
{ title: '@open and @close event', anchor: 'openAndClose' },
{ title: '@focus and @blur event', anchor: 'focusAndBlur' },
{ title: 'Customized Picker Labels', anchor: 'customPickerLabels' },
{ title: 'Adjust Input Width', anchor: 'inputWidth' },
{ title: 'Auto-Scroll', anchor: 'autoScroll' },
{ title: 'More Powerful format String', anchor: 'morePowerfulFormat' },
{ title: 'Customized Buttons And Icon', anchor: 'customButtonIcon' },
{ title: 'Fixed Dropdown Button', anchor: 'fixedDropdownButton' },
{ title: 'Drop Direction', anchor: 'dropDirection' }
]
}
},
methods: {
changeHandler (eventData) {
if (this.muteFlowListener) { return }
this.latestDataFlow = eventData
this.demoArgs = undefined
},
otherChangeHandler (eventData, arg1, arg2) {
if (this.muteFlowListener) { return }
this.latestDataFlow = eventData
this.demoArgs = {
arg1: arg1,
arg2: arg2
}
},
lazyChangeHandler (eventData) {
this.lazyChangeData = eventData
this.lazyEventTs = new Date().toLocaleString()
},
lazyInputHandler (eventData) {
this.lazyInputData = eventData
}
},
mounted () {
window.setTimeout(() => {
this.muteFlowListener = false
}, 1000)
}
}
</script>
<template lang="pug">
section#mostlyUsedSamples
h2.section-title Common Usage
//- Default
sample-block#default
template(v-slot:title) Default
p(slot="description")
| Default to 24-hour format
code HH:mm
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
| <vue-timepicker></vue-timepicker>
template(v-slot:preview)
vue-timepicker
//- 12 Hours
sample-block#format12hours
template(v-slot:title) 12 Hours
p(slot="description")
| By properly define the
code format
| string, you can set timepicker in form of 12 hours
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
pre
| <!-- 12-hour sample 1 -->
| <vue-timepicker format="hh:mm A"></vue-timepicker>
|
| <!-- 12-hour sample 2 -->
| <vue-timepicker format="h:m a"></vue-timepicker>
template(v-slot:preview)
b 12-hour sample 1
p
vue-timepicker(format="hh:mm A")
b 12-hour sample 2
p
vue-timepicker(format="h:m a")
//- Seconds Picker
sample-block#seconds
template(v-slot:title) Seconds Picker
p(slot="description")
| You can trigger the seconds picker by adding
code ss
| or
code s
| in your format string.
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
| <vue-timepicker format="HH:mm:ss"></vue-timepicker>
template(v-slot:preview)
vue-timepicker(format="HH:mm:ss")
//- Customized Interval
sample-block#interval
template(v-slot:title) Customized Interval
p(slot="description")
| Timepicker also allows you to display minutes or seconds picker with certain interval, like a 10-minute interval
code 0, 10, 20, ... 50, 60
| for example
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
pre
| <!-- 10-minute interval -->
| <vue-timepicker :minute-interval="10"></vue-timepicker>
|
| <!-- 15-second interval -->
| <vue-timepicker format="HH:mm:ss" :second-interval="15"></vue-timepicker>
|
| <!-- 5-minute interval plus 10-second interval -->
| <vue-timepicker format="hh:mm:ss" :minute-interval="5" :second-interval="10"></vue-timepicker>
template(v-slot:preview)
b 10-minute interval
p
vue-timepicker(:minute-interval="10")
b 15-second interval
p
vue-timepicker(format="HH:mm:ss" :second-interval="15")
b 5-minute interval plus 10-second interval
p
vue-timepicker(format="hh:mm:ss" :minute-interval="5" :second-interval="10")
//- Using v-model
sample-block#vModel
template(v-slot:title)
| Using
code v-model
p(slot="description")
| Timepicker takes <code>v-model</code> value in object format by default.
template(v-slot:codes)
highlight-code(lang="javascript" data-title="JS")
pre
| // Define format and initial data
| data () {
| return {
| yourFormat: 'hh:mm:ss a',
| yourData: {
| hh: '03',
| mm: '05',
| ss: '00',
| a: 'am'
| }
| }
| }
highlight-code(lang="html" data-title="HTML")
| <vue-timepicker :format="yourFormat" v-model="yourData"></vue-timepicker>
template(v-slot:preview)
vue-timepicker(:format="yourFormat" v-model="yourData")
template(v-slot:data)
highlight-code(lang="json" data-title="`yourData` in live (JSON)") {{ yourData }}
//- String format `v-model`
sample-block#vModelWithString
template(v-slot:title)
code v-model
| with String Value
p(slot="description")
| From <code>v1.0.0+</code>, timepicker also supports <code>v-model</code> value in string format.
template(v-slot:codes)
highlight-code(lang="javascript" data-title="JS")
pre
| // Set initial data in string format
| data () {
| return {
| simpleStringValue: '02:30',
|
| // paired with format 'h:mm:ss A'
| yourStringValue: '3:mm:05 A',
|
| unsetStringValue: ''
| }
| }
highlight-code(lang="html" data-title="HTML")
pre
| <!-- default 24-hour sample -->
| <vue-timepicker v-model="simpleStringValue"></vue-timepicker>
|
| <!-- 12-hour format with partial value set -->
| <vue-timepicker v-model="yourStringValue" format="h:mm:ss A"></vue-timepicker>
|
| <!-- unset/unknown initial value -->
| <vue-timepicker v-model="unsetStringValue"></vue-timepicker>
template(v-slot:preview)
b default 24-hour sample
p
vue-timepicker(v-model="simpleStringValue")
span.inline-data-preview
| simpleStringValue
code "{{ simpleStringValue }}"
b 12-hour format with partial value set
p
vue-timepicker(v-model="yourStringValue" format="h:mm:ss A")
span.inline-data-preview
| yourStringValue:
code "{{ yourStringValue }}"
b unset/unknown initial value
p
vue-timepicker(v-model="unsetStringValue")
span.inline-data-preview
| unsetStringValue:
code "{{ unsetStringValue }}"
//- v-for Example
sample-block#vForSample
template(v-slot:title)
| Work with
code v-for
p(slot="description")
| Here's a quick sample of
code v-for
| usage
template(v-slot:codes)
highlight-code(lang="javascript" data-title="JS")
pre
| data () {
| return {
| yourDaysArray: [
| {start_time: {HH: '08', mm: '00'}, end_time: {HH: '09', mm: '00'}},
| {start_time: {HH: '15', mm: '00'}, end_time: {HH: '', mm: ''}},
| {start_time: {HH: '', mm: ''}, end_time: {HH: '13', mm: '30'}},
| {start_time: {HH: '', mm: ''}, end_time: {HH: '', mm: ''}}
| ]
| }
| }
highlight-code(lang="html" data-title="HTML")
pre
| <p v-for="(day, index) in yourDaysArray">
| <label>Day <span>{{</span> index + 1 <span>}}</span>: </label>
| <vue-timepicker v-model="day.start_time" placeholder="Start Time"></vue-timepicker>
| <span> to </span>
| <vue-timepicker v-model="day.end_time" placeholder="End Time"></vue-timepicker>
| </p>
template(v-slot:preview)
p(v-for="(day, index) in yourDaysArray")
label Day {{ index + 1 }}:
vue-timepicker(v-model="day.start_time" placeholder="Start Time")
span to
vue-timepicker(v-model="day.end_time" placeholder="End Time")
template(v-slot:data)
highlight-code(lang="json" data-title="`yourDaysArray` JSON in live") {{ yourDaysArray }}
//- Hour Range
sample-block#hourRange
template(v-slot:title) Hour Range
p(slot="description") Define the hour values you want and disable the rest
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
pre
| <!-- Hour Range Sample 1 -->
| <vue-timepicker :hour-range="[5, [8, 12], [14, 17], 19]"></vue-timepicker>
| <!-- >> Equals to :hour-range="[5, 8, 9, 10, 11, 12, 14, 15, 16, 17, 19]" -->
|
| <!-- Hour Range Sample 2 (12-hour format) -->
| <vue-timepicker :hour-range="['7a', '9a', '11a', '1p', ['3p', '5p'], '7p']" format="hh:mm a"></vue-timepicker>
| <!-- >> Equals to :hour-range="['7a', '9a', '11a', '1p', '3p', '4p', '5p', '7p']" -->
template(v-slot:preview)
b Hour Range Sample 1
p
vue-timepicker(:hour-range="[5, [8, 12], [14, 17], 19]")
b Hour Range Sample 2 (12-hour format)
p
vue-timepicker(:hour-range="['7a', '9a', '11a', '1p', ['3p', '5p'], '7p']" format="hh:mm a")
//- Minute Range
sample-block#minuteAndSecondRange
template(v-slot:title) Minute and Second Range
template(v-slot:description)
p Similar to Hour Range, you can set available minute/second values base on your needs.
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
pre
| <!-- Minute range only -->
| <vue-timepicker :minute-range="[0, 6, [10, 30], 42, 50]"></vue-timepicker>
|
| <!-- Minute range + 5-minute interval -->
| <vue-timepicker :minute-range="[0, 6, [10, 30], 42, 50]" :minute-interval="5"></vue-timepicker>
|
| <!-- Second range only -->
| <vue-timepicker format="H:m:s" :second-range="[0, 6, [10, 30], 42, 50]"></vue-timepicker>
|
| <!-- Second range + 10-second interval -->
| <vue-timepicker format="H:m:s" :second-range="[0, 6, [10, 30], 42, 50]" :second-interval="10"></vue-timepicker>
|
| <!-- Minute and Second ranges + 10-minute interval + 5-second interval -->
| <vue-timepicker format="HH:mm:ss" :minute-range="[0, 6, [10, 30], 42, 50]" :second-range="[0, 6, [10, 30], 42, 50]" :minute-interval="10" :second-interval="5"></vue-timepicker>
template(v-slot:preview)
b Minute range only
p
vue-timepicker(:minute-range="[0, 6, [10, 30], 42, 50]")
b Minute range + 5-minute interval
p
vue-timepicker(:minute-range="[0, 6, [10, 30], 42, 50]" :minute-interval="5")
b Second range only
p
vue-timepicker(format="H:m:s" :second-range="[0, 6, [10, 30], 42, 50]")
b Second range + 10-second interval
p
vue-timepicker(format="H:m:s" :second-range="[0, 6, [10, 30], 42, 50]" :second-interval="10")
b Minute and Second ranges + 10-minute interval + 5-second interval
p
vue-timepicker(format="HH:mm:ss" :minute-range="[0, 6, [10, 30], 42, 50]" :second-range="[0, 6, [10, 30], 42, 50]" :minute-interval="10" :second-interval="5")
//- Hide Disabled Items
sample-block#hideDisabledItems
template(v-slot:title) Hide Disabled Items
template(v-slot:description)
p Here're four kinds of helper properties to let you hide the values excluded by the <code>hour-range</code>, <code>minute-range</code>, and <code>second-range</code>.
ul
li
b hide-disabled-items
| : Hide <b>all</b> disabled items - hour, minute, and seconds.
li
b hide-disabled-hours
| : Hide disabled <b>hour</b> valus only.
li
b hide-disabled-minutes
| : Hide disabled <b>minute</b> values only.
li
b hide-disabled-seconds
| : Hide disabled <b>second</b> values only.
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
pre
| <!-- hide-disabled-items -->
| <vue-timepicker hide-disabled-items format="HH:mm:ss" :hour-range="[[9, 17]]" :minute-range="[0, 10, 15, 30, 50]" :second-range="[5, 15, 25, 45]"></vue-timepicker>
|
| <!-- hide-disabled-hours -->
| <vue-timepicker hide-disabled-hours format="HH:mm:ss" :hour-range="[[9, 17]]" :minute-range="[0, 10, 15, 30, 50]" :second-range="[5, 15, 25, 45]"></vue-timepicker>
|
| <!-- hide-disabled-minutes -->
| <vue-timepicker hide-disabled-minutes format="HH:mm:ss" :hour-range="[[9, 17]]" :minute-range="[0, 10, 15, 30, 50]" :second-range="[5, 15, 25, 45]"></vue-timepicker>
|
| <!-- hide-disabled-seconds -->
| <vue-timepicker hide-disabled-seconds format="HH:mm:ss" :hour-range="[[9, 17]]" :minute-range="[0, 10, 15, 30, 50]" :second-range="[5, 15, 25, 45]"></vue-timepicker>
template(v-slot:preview)
b hide-disabled-items
p
vue-timepicker(hide-disabled-items format="HH:mm:ss" :hour-range="[[9, 17]]" :minute-range="[0, 10, 15, 30, 50]" :second-range="[5, 15, 25, 45]")
b hide-disabled-hours
p
vue-timepicker(hide-disabled-hours format="HH:mm:ss" :hour-range="[[9, 17]]" :minute-range="[0, 10, 15, 30, 50]" :second-range="[5, 15, 25, 45]")
b hide-disabled-minutes
p
vue-timepicker(hide-disabled-minutes format="HH:mm:ss" :hour-range="[[9, 17]]" :minute-range="[0, 10, 15, 30, 50]" :second-range="[5, 15, 25, 45]")
b hide-disabled-seconds
p
vue-timepicker(hide-disabled-seconds format="HH:mm:ss" :hour-range="[[9, 17]]" :minute-range="[0, 10, 15, 30, 50]" :second-range="[5, 15, 25, 45]")
//- Close on Complete
sample-block#closeOnComplete
template(v-slot:title) Close on Complete
p(slot="description")
| Automatically close the dropdown when user finish selecting <b>all</b> of the required fields.
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
pre
| <!-- Auto-close on complete -->
| <vue-timepicker format="hh:mm A" close-on-complete></vue-timepicker>
|
| <!-- Default - close by clicking anywhere outside of the dropdown -->
| <vue-timepicker format="hh:mm A"></vue-timepicker>
template(v-slot:preview)
b Auto-close on complete
p
vue-timepicker(format="hh:mm A" close-on-complete)
b Default - close by clicking anywhere outside of the dropdown
p
vue-timepicker(format="hh:mm A")
//- Hide Clear Button
sample-block#hideClearButton
template(v-slot:title) Hide Clear Button
p(slot="description")
| If you don't want to expose the clear button in the UI,
code hide-clear-button
| property will do the trick.
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
| <vue-timepicker hide-clear-button></vue-timepicker>
template(v-slot:preview)
vue-timepicker(hide-clear-button)
//- Disable Picker
sample-block#disablePicker
template(v-slot:title) Disable Picker
p(slot="description")
| Completely disable the picker.
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
| <vue-timepicker disabled></vue-timepicker>
template(v-slot:preview)
vue-timepicker(disabled)
//- @change Sample
sample-block#onChangeSample
template(v-slot:title)
| The
code change
| Event
template(v-slot:description)
p A <code>change</code> event will be triggered every time the user alters timepicker's value.
p Unlike the <code>v-model</code>, which only returns data in your predefined format, <code>change</code> event will return a full package of all supported time tokens.
p Started from <code>v0.2.2</code>, a <code>displayTime</code> string value is also included in the return data of <code>change</code> event.
p Play around with the two pickers below to see their data changes in live.
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
pre
| <!-- No argument -->
| <vue-timepicker v-model="demoData1" @change="changeHandler"></vue-timepicker>
|
| <!-- Custom argument -->
| <vue-timepicker v-model="demoData2" @change="otherChangeHandler($event, 'foo', 42)"></vue-timepicker>
highlight-code(lang="javascript" data-title="JS")
pre
| methods: {
| // No argument
| changeHandler (eventData) {
| // eventData -> {data: {HH:..., mm:...}, displayTime: 'HH:mm'}
| },
|
| // Customized arguments
| otherChangeHandler (eventData, arg1, arg2) {
| // eventData -> {data: {HH:..., mm:...}, displayTime: 'HH:mm'}
| // arg1 -> 'foo'
| // arg2 -> 42
| }
| }
template(v-slot:preview)
b No argument
p
vue-timepicker(v-model="demoData1" @change="changeHandler")
b With Custom arguments ('foo', 42)
p
vue-timepicker(v-model="demoData2" @change="otherChangeHandler($event, 'foo', 42)")
template(v-if="latestDataFlow || demoArgs" slot="data")
highlight-code(v-if="latestDataFlow" lang="json" data-title="The `@change` event data") {{ latestDataFlow }}
highlight-code(v-if="demoArgs" lang="json" data-title="Received Custom Arguments") {{ demoArgs }}
highlight-code(v-if="latestDataFlow" lang="json" data-title="`v-model` value") {{ demoArgs ? demoData2 : demoData1 }}
//- Lazy Event Mode
sample-block#lazyEvents
template(v-slot:title) Lazy Event Mode
template(v-slot:description)
p When <code>lazy</code> event mode is toggled on, only an actual user behavior can trigger the <code>input</code> and <code>change</code> events. Which are:
ul
li The user opened the dropdown and picked a new value
li The user clicked the ("x") clear button
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
| <vue-timepicker lazy format="hh:mm:ss a"></vue-timepicker>
template(v-slot:preview)
p
vue-timepicker(v-model="lazyData" lazy format="hh:mm:ss a" @input="lazyInputHandler" @change="lazyChangeHandler")
span.inline-data-preview(v-if="lazyEventTs")
b Last <code>change</code> event timestamp:
| {{ lazyEventTs }}
template(v-slot:data)
highlight-code(v-if="lazyInputData" lang="json" data-title="The lazy `input` event data") {{ lazyInputData }}
highlight-code(v-if="lazyChangeData" lang="json" data-title="The lazy `change` event data") {{ lazyChangeData }}
//- Keyboard Support
sample-block#kbSupport
template(v-slot:title) Keyboard Support
template(v-slot:description)
p
b Basic Keyboard Support:
ul
li
b Tab
| : Focus or blur the Timepicker
li
b Esc
| : Close the dropdown
p
b Advance Keyboard Support:
ul
li
b Arrow Keys
| : Navigate between valid (non-disabled) values and columns
li
b Space
| or
b Enter
| : Select the focusing item
p Try tabbing through the following inputs to see the difference between the <b>Default Timepicker</b> and the <b>Timepicker with Advanced Keyboard support</b>.
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
pre
| <label for="otherInput">Text Input<label/>
| <input id="otherInput" type="text" placeholder="Text" />
|
| <!-- Default, with minimal keyboard support -->
| <label for="simplePicker">Default Vue Timepicker<label/>
| <vue-timepicker id="simplePicker"></vue-timepicker>
|
| <label for="moreInput">Number Input<label/>
| <input id="moreInput" type="number" placeholder="Number" />
|
| <!-- Advanced Keyboard Support Enabled -->
| <label for="pickerKB">Vue Timepicker with Advanced Keyboard support<label/>
| <vue-timepicker advanced-keyboard format="h:mm:ss A" :hour-range="[['7a', '5p']]" id="pickerKB"></vue-timepicker>
|
| <label for="oneMoreInput">One More Text Input<label/>
| <input id="oneMoreInput" type="text" placeholder="More Text" />
template(v-slot:preview)
b
label(for="otherInput") Text Input
p
input#otherInput.native-input(type="text" placeholder="Text")
b
label(for="simplePicker") Default Vue Timepicker
p
vue-timepicker(id="simplePicker")
b
label(for="moreInput") Number Input
p
input#moreInput.native-input(type="number" placeholder="Number")
b
label(for="pickerKB") Vue Timepicker with Advanced Keyboard support
p
vue-timepicker(id="pickerKB" format="h:mm:ss A" :hour-range="[['7a', '5p']]" advanced-keyboard)
b
label(for="oneMoreInput") One More Text Input
p
input#oneMoreInput.native-input(type="text" placeholder="More Text")
//- Manual Input
sample-block#manualInput
template(v-slot:title) Manual Input
p(slot="description")
| Allow users to input values manually. Please note that the additional <code>hide-dropdown</code> option works with <code>manual-input</code> mode only.
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
pre
| <!-- 24-hour format with empty init value -->
| <vue-timepicker manual-input></vue-timepicker>
|
| <!-- 12-hour format with a predefined value -->
| <vue-timepicker format="h:mm a" v-model="manualStringValue" manual-input></vue-timepicker>
|
| <!-- Manual input + hide dropdown -->
| <vue-timepicker manual-input hide-dropdown></vue-timepicker>
highlight-code(lang="javascript" data-title="JS")
pre
| data () {
| return {
| manualStringValue: '8:15 pm'
| }
| }
template(v-slot:preview)
b 24-hour format with empty init value
p
vue-timepicker(manual-input)
b 12-hour format with a predefined value
p
vue-timepicker(format="h:mm a" v-model="manualStringValue" manual-input)
b Manual input + hide dropdown
p
vue-timepicker(manual-input hide-dropdown)
//- Open And Close Event
sample-block#openAndClose
template(v-slot:title)
code open
| and
code close
| event
p(slot="description")
| Help to identify the current state of the dropdown picker.
template(v-slot:codes)
highlight-code(lang="javascript" data-title="JS")
pre
| // Define a variable for logging the status
| data () {
| return {
| dropdownStatus: 'closed'
| }
| }
highlight-code(lang="html" data-title="HTML")
pre
| <p>Dropdown Status: I'm <span>{{</span>dropdownStatus<span>}}</span>!</p>
|
| <vue-timepicker @open="dropdownStatus = 'opened'" @close="dropdownStatus = 'closed'"></vue-timepicker>
template(v-slot:preview)
b Dropdown Status: I'm {{dropdownStatus}}!
p
vue-timepicker(@open="dropdownStatus = 'opened'" @close="dropdownStatus = 'closed'")
//- Focus And Blur Event
sample-block#focusAndBlur
template(v-slot:title)
code focus
| and
code blur
| event
p(slot="description")
| It works with Manual Input mode. Helps to identify the focus/blur state of the Timepicker's input. Especially useful when the dropdown is force hidden by <code>hide-dropdown</code>.
template(v-slot:codes)
highlight-code(lang="javascript" data-title="JS")
pre
| data () {
| return {
| // variable for the input state
| focusState: 'blurred',
|
| // variable for the dropdown state
| dropdownState: 'closed'
| }
| }
highlight-code(lang="html" data-title="HTML")
pre
| <span>Focus State: <span>{{</span>focusState<span>}}</span></span>
| <span>Dropdown State: <span>{{</span>dropdownState<span>}}</span></span>
|
| <vue-timepicker manual-input hide-dropdown @focus="focusState = 'focused'" @blur="focusState = 'blurred'" @open="dropdownState = 'opened'" @close="dropdownState = 'closed'"></vue-timepicker>
template(v-slot:preview)
b Focus State: {{focusState}}
span  / 
b Dropdown State: {{ dropdownState }}
p
vue-timepicker(manual-input hide-dropdown @focus="focusState = 'focused'" @blur="focusState = 'blurred'" @open="dropdownState = 'opened'" @close="dropdownState = 'closed'")
//- Custom Labels
sample-block#customPickerLabels
template(v-slot:title) Customized Picker Labels
p(slot="description")
| Define customized labels for hour, minute, second, and APM pickers.
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
pre
| <!-- 24-hour format with customized hour and minute labels -->
| <vue-timepicker hour-label="heure" minute-label="minute"></vue-timepicker>
|
| <!-- 12-hour format with customized am/pm text -->
| <vue-timepicker hour-label="时" minute-label="分" second-label="秒" apm-label="午" am-text="上午" pm-text="下午" format="h:mm:ss a"></vue-timepicker>
template(v-slot:preview)
b 24-hour format with customized hour and minute label
p
vue-timepicker(hour-label="heure" minute-label="minute")
b 12-hour format with customized am/pm text
p
vue-timepicker(hour-label="时" minute-label="分" second-label="秒" apm-label="午" am-text="上午" pm-text="下午" format="h:mm:ss a")
//- Adjust Input Width
sample-block#inputWidth
template(v-slot:title) Adjust Input Width
p(slot="description")
| Helps you to adjust both the
code <input>
| and the dropdown picker's width
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
pre
| <!-- In `px` -->
| <vue-timepicker input-width="100px"></vue-timepicker>
|
| <!-- In `em` -->
| <vue-timepicker input-width="12em" format="HH:mm:ss"></vue-timepicker>
template(v-slot:preview)
b In `px`
p
vue-timepicker(input-width="100px")
b In `em`
p
vue-timepicker(input-width="12em" format="HH:mm:ss")
//- Auto Scroll
sample-block#autoScroll
template(v-slot:title) Auto-Scroll
p(slot="description") Auto-scroll to selected value on dropdown open.
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
pre
| <!-- Default format -->
| <vue-timepicker auto-scroll v-model="autoScrollData1"></vue-timepicker>
|
| <!-- 12-hour format -->
| <vue-timepicker auto-scroll format="h:mm:ss a" v-model="autoScrollData2"></vue-timepicker>
highlight-code(lang="javascript" data-title="JS")
pre
| // Initial values
| data () {
| return {
| autoScrollData1: '08:40',
| autoScrollData2: '5:30:20 pm'
| }
| }
template(v-slot:preview)
b Default format
p
vue-timepicker(auto-scroll v-model="autoScrollData1")
b 12-hour format
p
vue-timepicker(auto-scroll format="h:mm:ss a" v-model="autoScrollData2")
//- More Powerful format String
sample-block#morePowerfulFormat
template(v-slot:title) More Powerful <code>format</code> String
template(slot="description")
p The <code>format</code> parameter becomes even more powerful started from <code>v1.1.2</code>.
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
pre
| <!-- Use without "hour" -->
| <vue-timepicker format="mm:ss"></vue-timepicker>
| <vue-timepicker format="m:s"></vue-timepicker>
|
| <!-- Make AM/PM the first column in the dropdown -->
| <vue-timepicker format="A hh:mm" v-model="apmFirst1"></vue-timepicker>
| <vue-timepicker format="ah時m分" v-model="apmFirst2" am-text="午前" pm-text="午後"></vue-timepicker>
|
| <!-- Hour + APM only -->
| <vue-timepicker format="ha"></vue-timepicker>
| <vue-timepicker format="hh A"></vue-timepicker>
|
| <!-- One slot only -->
| <!-- Not recommended, though :) -->
| <vue-timepicker format="h" input-width="60px"></vue-timepicker>
| <vue-timepicker format="mm" input-width="60px"></vue-timepicker>
| <vue-timepicker format="ss" input-width="60px"></vue-timepicker>
| <vue-timepicker format="a" input-width="60px"></vue-timepicker>
highlight-code(lang="javascript" data-title="JS")
pre
| // Initial values
| data () {
| return {
| apmFirst1: 'AM 03:15',
| // -> Equivalent to:
| // apmFirst1: {
| // A: 'AM',
| // hh: '03',
| // mm: '15'
| // }
|
| apmFirst2: 'pm9時6分'
| // -> Equivalent to:
| // apmFirst2: {
| // a: 'pm',
| // h: '9',
| // m: '6'
| // }
| }
| }
template(v-slot:preview)
b Use without "hour"
p
vue-timepicker(format="mm:ss")
|
vue-timepicker(format="m:s")
b Make AM/PM the first column in the dropdown
p
vue-timepicker(format="A hh:mm" v-model="apmFirst1")
|
vue-timepicker(format="ah時m分" v-model="apmFirst2" am-text="午前" pm-text="午後")
b Hour + APM only
p
vue-timepicker(format="ha")
|
vue-timepicker(format="hh A")
b One slot only
p
vue-timepicker(format="h" input-width="60px")
|
vue-timepicker(format="mm" input-width="60px")
|
vue-timepicker(format="ss" input-width="60px")
|
vue-timepicker(format="a" input-width="60px")
//- Custom Button And Icon
sample-block#customButtonIcon
template(v-slot:title) Customized Buttons And Input Icon
template(v-slot:description)
p You can customize the clear button, and the dropdown button with your own icon/image starts from <code>v1.1.4+</code>. There's an additional slot for the input icon as well.
p Please note that Vue v2.6.0+ introduces a significant update of the <b>Named Slots</b> syntax. Check the <a href="https://vuejs.org/v2/guide/components-slots.html#Named-Slots" target="_black">official documentation</a> for more information.
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
pre
| <!-- For Vue 2.6.0+ -->
|
| <!-- Input icon (image) -->
| <vue-timepicker>
| <template v-slot:icon>
| <img src="$YOUR_ICON_SRC" />
| </template>
| </vue-timepicker>
|
| <!-- Customized clear button (image) -->
| <vue-timepicker>
| <template v-slot:clearButton>
| <img src="$YOUR_CUSTOM_IMAGE_SRC" />
| </template>
| </vue-timepicker>
|
| <!-- Customized dropdown button (character entity) -->
| <vue-timepicker manual-input hide-dropdown>
| <template v-slot:dropdownButton>&#x02263;</template>
| </vue-timepicker>
template(v-slot:preview)
b Input icon (image)
p
vue-timepicker
template(v-slot:icon)
img(src="https://i.postimg.cc/CLkZcW46/custom-clock.png")
b Customized clear button (image)
p
vue-timepicker(v-model="customCloseBtnValue")
template(v-slot:clearButton)
img(src="https://i.postimg.cc/Y0f6RHF8/custom-close.png")
b Customized dropdown button (character entity)
p
vue-timepicker(manual-input hide-dropdown)
template(v-slot:dropdownButton) ≣
//- Fixed Dropdown Button
sample-block#fixedDropdownButton
template(v-slot:title) Fixed Dropdown Button
template(v-slot:description)
p You can make the dropdown button always visible in the UI with <code>fixed-dropdown-button</code>.
p When paired with a customized dropdown button, it's similar to an input icon on the righthand side.
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
pre
| <!-- Default dropdown button -->
| <vue-timepicker fixed-dropdown-button></vue-timepicker>
|
| <!-- Customized + fixed dropdown button -->
| <vue-timepicker fixed-dropdown-button>
| <template v-slot:dropdownButton>
| <img src="$YOUR_BUTTON_IMAGE_SRC" />
| </template>
| </vue-timepicker>
|
| <!-- To display only one button on the right -->
| <!-- Customized + fixed dropdown button + hide clear button -->
| <vue-timepicker fixed-dropdown-button hide-clear-button>
| <template v-slot:dropdownButton>
| <img src="$YOUR_BUTTON_IMAGE_SRC" />
| </template>
| </vue-timepicker>
template(v-slot:preview)
b Default dropdown button
p
vue-timepicker(fixed-dropdown-button)
b Customized + fixed dropdown button
p
vue-timepicker(fixed-dropdown-button)
template(v-slot:dropdownButton)
img(src="https://i.postimg.cc/CLkZcW46/custom-clock.png")
b Customized + fixed dropdown button + hide clear button
p
vue-timepicker(fixed-dropdown-button hide-clear-button)
template(v-slot:dropdownButton)
img(src="https://i.postimg.cc/CLkZcW46/custom-clock.png")
//- Drop Direction
sample-block#dropDirection
template(v-slot:title) Drop Direction
template(v-slot:description)
p Change dropdown direction when needed (<code>v1.1.5+</code>). Accepting values:
ul
li
b down
| : Default value.
li
b up
| : Force open the dropdown above the input.
li
b auto
| : Auto detects available height and opens the dropdown on top if there are not enough spaces below the input.
template(v-slot:codes)
highlight-code(lang="html" data-title="HTML")
pre
| <!-- Drop Direction Up -->
| <vue-timepicker drop-direction="up"></vue-timepicker>
|
| <!-- Auto Drop Direction -->
| <div id="auto-dropdown-containter">
| <!-- Defined Container -->
| <vue-timepicker drop-direction="auto" container-id="auto-dropdown-containter"></vue-timepicker>
| <!-- Default (document body) -->
| <vue-timepicker drop-direction="auto"></vue-timepicker>
| </div>
template(v-slot:preview)
b Drop Direction Up
p
vue-timepicker(drop-direction="up")
#auto-dropdown-containter
.demo-title
b Auto Drop Direction
.demo-body
.inner
b Defined Container
p
vue-timepicker(drop-direction="auto" container-id="auto-dropdown-containter")
.inner
b Default (document body)
p
vue-timepicker(drop-direction="auto")
//- Footer Links
.footer-links
slot(name="footer-links")
//- Side Nav
.sidenav
nav
ul
li(v-for="(nav, navIdx) in sideNav" :key="navIdx")
a(:href="'#' + nav.anchor" v-text="nav.title")
</template>
<style lang="stylus">
@import '../assets/_variables.styl'
section#mostlyUsedSamples
.section-title
padding-left: 20%
.footer-links
padding: 5em 0 0 20%
a
cursor: pointer
.title
position: relative
margin-bottom: 1.5em
a.anchor
position: absolute
left: -1em
.description
margin-left: 1.5em
.sidenav
position: fixed
width: 20%
bottom: 0
left: 0
max-height: calc(100vh - 50px)
overflow-y: auto
ul
padding: 0 0 0.5em 1.5em
margin: 0
list-style: square
li
padding: 0.15em 0
font-size: 0.8em
color: alpha($body-color, 0.4)
// Browser Native Input
input.native-input
box-sizing: border-box
border: 1px solid #d2d2d2
width: 10em
height: 2.2em
padding: 0.3em 0.5em
font-size: 1em
// Drop Direction Demo
#auto-dropdown-containter
margin-top: 1em
padding: 1em
background: rgba(0, 0, 0, 0.05)
border-radius: 5px
.demo-title
font-weight: 600
padding: 0 0 0.5em 0
.demo-body
display: flex
flex-flow: row nowrap
justify-content: flex-start
align-items: flex-start
.inner
margin-right: 0.5em
b
font-weight: normal
</style>
================================================
FILE: demo/src/main.js
================================================
import Vue from 'vue'
import VueHighlightJS from 'vue-highlight.js'
import javascript from 'highlight.js/lib/languages/javascript'
import json from 'highlight.js/lib/languages/json'
import vue from 'vue-highlight.js/lib/languages/vue'
import 'highlight.js/styles/docco.css'
import App from './App.vue'
Vue.config.productionTip = false
/*
* Use Vue Highlight.js
*/
Vue.use(VueHighlightJS, {
// Register only languages that you want
languages: {
javascript,
json,
vue
}
})
new Vue({
render: h => h(App),
}).$mount('#app')
================================================
FILE: demo/vue.config.js
================================================
module.exports = {
outputDir: '../gh-pages',
publicPath: process.env.NODE_ENV === 'production'
? '/vue2-timepicker/'
: '/'
}
================================================
FILE: dist/VueTimepicker.common.js
================================================
module.exports =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "fb15");
/******/ })
/************************************************************************/
/******/ ({
/***/ "00ee":
/***/ (function(module, exports, __webpack_require__) {
var wellKnownSymbol = __webpack_require__("b622");
var TO_STRING_TAG = wellKnownSymbol('toStringTag');
var test = {};
test[TO_STRING_TAG] = 'z';
module.exports = String(test) === '[object z]';
/***/ }),
/***/ "0366":
/***/ (function(module, exports, __webpack_require__) {
var aFunction = __webpack_require__("1c0b");
// optional / simple context binding
module.exports = function (fn, that, length) {
aFunction(fn);
if (that === undefined) return fn;
switch (length) {
case 0: return function () {
return fn.call(that);
};
case 1: return function (a) {
return fn.call(that, a);
};
case 2: return function (a, b) {
return fn.call(that, a, b);
};
case 3: return function (a, b, c) {
return fn.call(that, a, b, c);
};
}
return function (/* ...args */) {
return fn.apply(that, arguments);
};
};
/***/ }),
/***/ "057f":
/***/ (function(module, exports, __webpack_require__) {
var toIndexedObject = __webpack_require__("fc6a");
var nativeGetOwnPropertyNames = __webpack_require__("241c").f;
var toString = {}.toString;
var windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames
? Object.getOwnPropertyNames(window) : [];
var getWindowNames = function (it) {
try {
return nativeGetOwnPropertyNames(it);
} catch (error) {
return windowNames.slice();
}
};
// fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window
module.exports.f = function getOwnPropertyNames(it) {
return windowNames && toString.call(it) == '[object Window]'
? getWindowNames(it)
: nativeGetOwnPropertyNames(toIndexedObject(it));
};
/***/ }),
/***/ "06cf":
/***/ (function(module, exports, __webpack_require__) {
var DESCRIPTORS = __webpack_require__("83ab");
var propertyIsEnumerableModule = __webpack_require__("d1e7");
var createPropertyDescriptor = __webpack_require__("5c6c");
var toIndexedObject = __webpack_require__("fc6a");
var toPrimitive = __webpack_require__("c04e");
var has = __webpack_require__("5135");
var IE8_DOM_DEFINE = __webpack_require__("0cfb");
var nativeGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
// `Object.getOwnPropertyDescriptor` method
// https://tc39.github.io/ecma262/#sec-object.getownpropertydescriptor
exports.f = DESCRIPTORS ? nativeGetOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) {
O = toIndexedObject(O);
P = toPrimitive(P, true);
if (IE8_DOM_DEFINE) try {
return nativeGetOwnPropertyDescriptor(O, P);
} catch (error) { /* empty */ }
if (has(O, P)) return createPropertyDescriptor(!propertyIsEnumerableModule.f.call(O, P), O[P]);
};
/***/ }),
/***/ "0cfb":
/***/ (function(module, exports, __webpack_require__) {
var DESCRIPTORS = __webpack_require__("83ab");
var fails = __webpack_require__("d039");
var createElement = __webpack_require__("cc12");
// Thank's IE8 for his funny defineProperty
module.exports = !DESCRIPTORS && !fails(function () {
return Object.defineProperty(createElement('div'), 'a', {
get: function () { return 7; }
}).a != 7;
});
/***/ }),
/***/ "1276":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var fixRegExpWellKnownSymbolLogic = __webpack_require__("d784");
var isRegExp = __webpack_require__("44e7");
var anObject = __webpack_require__("825a");
var requireObjectCoercible = __webpack_require__("1d80");
var speciesConstructor = __webpack_require__("4840");
var advanceStringIndex = __webpack_require__("8aa5");
var toLength = __webpack_require__("50c4");
var callRegExpExec = __webpack_require__("14c3");
var regexpExec = __webpack_require__("9263");
var fails = __webpack_require__("d039");
var arrayPush = [].push;
var min = Math.min;
var MAX_UINT32 = 0xFFFFFFFF;
// babel-minify transpiles RegExp('x', 'y') -> /x/y and it causes SyntaxError
var SUPPORTS_Y = !fails(function () { return !RegExp(MAX_UINT32, 'y'); });
// @@split logic
fixRegExpWellKnownSymbolLogic('split', 2, function (SPLIT, nativeSplit, maybeCallNative) {
var internalSplit;
if (
'abbc'.split(/(b)*/)[1] == 'c' ||
'test'.split(/(?:)/, -1).length != 4 ||
'ab'.split(/(?:ab)*/).length != 2 ||
'.'.split(/(.?)(.?)/).length != 4 ||
'.'.split(/()()/).length > 1 ||
''.split(/.?/).length
) {
// based on es5-shim implementation, need to rework it
internalSplit = function (separator, limit) {
var string = String(requireObjectCoercible(this));
var lim = limit === undefined ? MAX_UINT32 : limit >>> 0;
if (lim === 0) return [];
if (separator === undefined) return [string];
// If `separator` is not a regex, use native split
if (!isRegExp(separator)) {
return nativeSplit.call(string, separator, lim);
}
var output = [];
var flags = (separator.ignoreCase ? 'i' : '') +
(separator.multiline ? 'm' : '') +
(separator.unicode ? 'u' : '') +
(separator.sticky ? 'y' : '');
var lastLastIndex = 0;
// Make `global` and avoid `lastIndex` issues by working with a copy
var separatorCopy = new RegExp(separator.source, flags + 'g');
var match, lastIndex, lastLength;
while (match = regexpExec.call(separatorCopy, string)) {
lastIndex = separatorCopy.lastIndex;
if (lastIndex > lastLastIndex) {
output.push(string.slice(lastLastIndex, match.index));
if (match.length > 1 && match.index < string.length) arrayPush.apply(output, match.slice(1));
lastLength = match[0].length;
lastLastIndex = lastIndex;
if (output.length >= lim) break;
}
if (separatorCopy.lastIndex === match.index) separatorCopy.lastIndex++; // Avoid an infinite loop
}
if (lastLastIndex === string.length) {
if (lastLength || !separatorCopy.test('')) output.push('');
} else output.push(string.slice(lastLastIndex));
return output.length > lim ? output.slice(0, lim) : output;
};
// Chakra, V8
} else if ('0'.split(undefined, 0).length) {
internalSplit = function (separator, limit) {
return separator === undefined && limit === 0 ? [] : nativeSplit.call(this, separator, limit);
};
} else internalSplit = nativeSplit;
return [
// `String.prototype.split` method
// https://tc39.github.io/ecma262/#sec-string.prototype.split
function split(separator, limit) {
var O = requireObjectCoercible(this);
var splitter = separator == undefined ? undefined : separator[SPLIT];
return splitter !== undefined
? splitter.call(separator, O, limit)
: internalSplit.call(String(O), separator, limit);
},
// `RegExp.prototype[@@split]` method
// https://tc39.github.io/ecma262/#sec-regexp.prototype-@@split
//
// NOTE: This cannot be properly polyfilled in engines that don't support
// the 'y' flag.
function (regexp, limit) {
var res = maybeCallNative(internalSplit, regexp, this, limit, internalSplit !== nativeSplit);
if (res.done) return res.value;
var rx = anObject(regexp);
var S = String(this);
var C = speciesConstructor(rx, RegExp);
var unicodeMatching = rx.unicode;
var flags = (rx.ignoreCase ? 'i' : '') +
(rx.multiline ? 'm' : '') +
(rx.unicode ? 'u' : '') +
(SUPPORTS_Y ? 'y' : 'g');
// ^(? + rx + ) is needed, in combination with some S slicing, to
// simulate the 'y' flag.
var splitter = new C(SUPPORTS_Y ? rx : '^(?:' + rx.source + ')', flags);
var lim = limit === undefined ? MAX_UINT32 : limit >>> 0;
if (lim === 0) return [];
if (S.length === 0) return callRegExpExec(splitter, S) === null ? [S] : [];
var p = 0;
var q = 0;
var A = [];
while (q < S.length) {
splitter.lastIndex = SUPPORTS_Y ? q : 0;
var z = callRegExpExec(splitter, SUPPORTS_Y ? S : S.slice(q));
var e;
if (
z === null ||
(e = min(toLength(splitter.lastIndex + (SUPPORTS_Y ? 0 : q)), S.length)) === p
) {
q = advanceStringIndex(S, q, unicodeMatching);
} else {
A.push(S.slice(p, q));
if (A.length === lim) return A;
for (var i = 1; i <= z.length - 1; i++) {
A.push(z[i]);
if (A.length === lim) return A;
}
q = p = e;
}
}
A.push(S.slice(p));
return A;
}
];
}, !SUPPORTS_Y);
/***/ }),
/***/ "14c3":
/***/ (function(module, exports, __webpack_require__) {
var classof = __webpack_require__("c6b6");
var regexpExec = __webpack_require__("9263");
// `RegExpExec` abstract operation
// https://tc39.github.io/ecma262/#sec-regexpexec
module.exports = function (R, S) {
var exec = R.exec;
if (typeof exec === 'function') {
var result = exec.call(R, S);
if (typeof result !== 'object') {
throw TypeError('RegExp exec method returned something other than an Object or null');
}
return result;
}
if (classof(R) !== 'RegExp') {
throw TypeError('RegExp#exec called on incompatible receiver');
}
return regexpExec.call(R, S);
};
/***/ }),
/***/ "159b":
/***/ (function(module, exports, __webpack_require__) {
var global = __webpack_require__("da84");
var DOMIterables = __webpack_require__("fdbc");
var forEach = __webpack_require__("17c2");
var createNonEnumerableProperty = __webpack_require__("9112");
for (var COLLECTION_NAME in DOMIterables) {
var Collection = global[COLLECTION_NAME];
var CollectionPrototype = Collection && Collection.prototype;
// some Chrome versions have non-configurable methods on DOMTokenList
if (CollectionPrototype && CollectionPrototype.forEach !== forEach) try {
createNonEnumerableProperty(CollectionPrototype, 'forEach', forEach);
} catch (error) {
CollectionPrototype.forEach = forEach;
}
}
/***/ }),
/***/ "17c2":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var $forEach = __webpack_require__("b727").forEach;
var arrayMethodIsStrict = __webpack_require__("a640");
var arrayMethodUsesToLength = __webpack_require__("ae40");
var STRICT_METHOD = arrayMethodIsStrict('forEach');
var USES_TO_LENGTH = arrayMethodUsesToLength('forEach');
// `Array.prototype.forEach` method implementation
// https://tc39.github.io/ecma262/#sec-array.prototype.foreach
module.exports = (!STRICT_METHOD || !USES_TO_LENGTH) ? function forEach(callbackfn /* , thisArg */) {
return $forEach(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
} : [].forEach;
/***/ }),
/***/ "1be4":
/***/ (function(module, exports, __webpack_require__) {
var getBuiltIn = __webpack_require__("d066");
module.exports = getBuiltIn('document', 'documentElement');
/***/ }),
/***/ "1c0b":
/***/ (function(module, exports) {
module.exports = function (it) {
if (typeof it != 'function') {
throw TypeError(String(it) + ' is not a function');
} return it;
};
/***/ }),
/***/ "1c7e":
/***/ (function(module, exports, __webpack_require__) {
var wellKnownSymbol = __webpack_require__("b622");
var ITERATOR = wellKnownSymbol('iterator');
var SAFE_CLOSING = false;
try {
var called = 0;
var iteratorWithReturn = {
next: function () {
return { done: !!called++ };
},
'return': function () {
SAFE_CLOSING = true;
}
};
iteratorWithReturn[ITERATOR] = function () {
return this;
};
// eslint-disable-next-line no-throw-literal
Array.from(iteratorWithReturn, function () { throw 2; });
} catch (error) { /* empty */ }
module.exports = function (exec, SKIP_CLOSING) {
if (!SKIP_CLOSING && !SAFE_CLOSING) return false;
var ITERATION_SUPPORT = false;
try {
var object = {};
object[ITERATOR] = function () {
return {
next: function () {
return { done: ITERATION_SUPPORT = true };
}
};
};
exec(object);
} catch (error) { /* empty */ }
return ITERATION_SUPPORT;
};
/***/ }),
/***/ "1d80":
/***/ (function(module, exports) {
// `RequireObjectCoercible` abstract operation
// https://tc39.github.io/ecma262/#sec-requireobjectcoercible
module.exports = function (it) {
if (it == undefined) throw TypeError("Can't call method on " + it);
return it;
};
/***/ }),
/***/ "1dde":
/***/ (function(module, exports, __webpack_require__) {
var fails = __webpack_require__("d039");
var wellKnownSymbol = __webpack_require__("b622");
var V8_VERSION = __webpack_require__("2d00");
var SPECIES = wellKnownSymbol('species');
module.exports = function (METHOD_NAME) {
// We can't use this feature detection in V8 since it causes
// deoptimization and serious performance degradation
// https://github.com/zloirock/core-js/issues/677
return V8_VERSION >= 51 || !fails(function () {
var array = [];
var constructor = array.constructor = {};
constructor[SPECIES] = function () {
return { foo: 1 };
};
return array[METHOD_NAME](Boolean).foo !== 1;
});
};
/***/ }),
/***/ "23cb":
/***/ (function(module, exports, __webpack_require__) {
var toInteger = __webpack_require__("a691");
var max = Math.max;
var min = Math.min;
// Helper for a popular repeating case of the spec:
// Let integer be ? ToInteger(index).
// If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length).
module.exports = function (index, length) {
var integer = toInteger(index);
return integer < 0 ? max(integer + length, 0) : min(integer, length);
};
/***/ }),
/***/ "23e7":
/***/ (function(module, exports, __webpack_require__) {
var global = __webpack_require__("da84");
var getOwnPropertyDescriptor = __webpack_require__("06cf").f;
var createNonEnumerableProperty = __webpack_require__("9112");
var redefine = __webpack_require__("6eeb");
var setGlobal = __webpack_require__("ce4e");
var copyConstructorProperties = __webpack_require__("e893");
var isForced = __webpack_require__("94ca");
/*
options.target - name of the target object
options.global - target is the global object
options.stat - export as static methods of target
options.proto - export as prototype methods of target
options.real - real prototype method for the `pure` version
options.forced - export even if the native feature is available
options.bind - bind methods to the target, required for the `pure` version
options.wrap - wrap constructors to preventing global pollution, required for the `pure` version
options.unsafe - use the simple assignment of property instead of delete + defineProperty
options.sham - add a flag to not completely full polyfills
options.enumerable - export as enumerable property
options.noTargetGet - prevent calling a getter on target
*/
module.exports = function (options, source) {
var TARGET = options.target;
var GLOBAL = options.global;
var STATIC = options.stat;
var FORCED, target, key, targetProperty, sourceProperty, descriptor;
if (GLOBAL) {
target = global;
} else if (STATIC) {
target = global[TARGET] || setGlobal(TARGET, {});
} else {
target = (global[TARGET] || {}).prototype;
}
if (target) for (key in source) {
sourceProperty = source[key];
if (options.noTargetGet) {
descriptor = getOwnPropertyDescriptor(target, key);
targetProperty = descriptor && descriptor.value;
} else targetProperty = target[key];
FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced);
// contained in target
if (!FORCED && targetProperty !== undefined) {
if (typeof sourceProperty === typeof targetProperty) continue;
copyConstructorProperties(sourceProperty, targetProperty);
}
// add a flag to not completely full polyfills
if (options.sham || (targetProperty && targetProperty.sham)) {
createNonEnumerableProperty(sourceProperty, 'sham', true);
}
// extend global
redefine(target, key, sourceProperty, options);
}
};
/***/ }),
/***/ "241c":
/***/ (function(module, exports, __webpack_require__) {
var internalObjectKeys = __webpack_require__("ca84");
var enumBugKeys = __webpack_require__("7839");
var hiddenKeys = enumBugKeys.concat('length', 'prototype');
// `Object.getOwnPropertyNames` method
// https://tc39.github.io/ecma262/#sec-object.getownpropertynames
exports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
return internalObjectKeys(O, hiddenKeys);
};
/***/ }),
/***/ "2532":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var $ = __webpack_require__("23e7");
var notARegExp = __webpack_require__("5a34");
var requireObjectCoercible = __webpack_require__("1d80");
var correctIsRegExpLogic = __webpack_require__("ab13");
// `String.prototype.includes` method
// https://tc39.github.io/ecma262/#sec-string.prototype.includes
$({ target: 'String', proto: true, forced: !correctIsRegExpLogic('includes') }, {
includes: function includes(searchString /* , position = 0 */) {
return !!~String(requireObjectCoercible(this))
.indexOf(notARegExp(searchString), arguments.length > 1 ? arguments[1] : undefined);
}
});
/***/ }),
/***/ "25f0":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var redefine = __webpack_require__("6eeb");
var anObject = __webpack_require__("825a");
var fails = __webpack_require__("d039");
var flags = __webpack_require__("ad6d");
var TO_STRING = 'toString';
var RegExpPrototype = RegExp.prototype;
var nativeToString = RegExpPrototype[TO_STRING];
var NOT_GENERIC = fails(function () { return nativeToString.call({ source: 'a', flags: 'b' }) != '/a/b'; });
// FF44- RegExp#toString has a wrong name
var INCORRECT_NAME = nativeToString.name != TO_STRING;
// `RegExp.prototype.toString` method
// https://tc39.github.io/ecma262/#sec-regexp.prototype.tostring
if (NOT_GENERIC || INCORRECT_NAME) {
redefine(RegExp.prototype, TO_STRING, function toString() {
var R = anObject(this);
var p = String(R.source);
var rf = R.flags;
var f = String(rf === undefined && R instanceof RegExp && !('flags' in RegExpPrototype) ? flags.call(R) : rf);
return '/' + p + '/' + f;
}, { unsafe: true });
}
/***/ }),
/***/ "2626":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var getBuiltIn = __webpack_require__("d066");
var definePropertyModule = __webpack_require__("9bf2");
var wellKnownSymbol = __webpack_require__("b622");
var DESCRIPTORS = __webpack_require__("83ab");
var SPECIES = wellKnownSymbol('species');
module.exports = function (CONSTRUCTOR_NAME) {
var Constructor = getBuiltIn(CONSTRUCTOR_NAME);
var defineProperty = definePropertyModule.f;
if (DESCRIPTORS && Constructor && !Constructor[SPECIES]) {
defineProperty(Constructor, SPECIES, {
configurable: true,
get: function () { return this; }
});
}
};
/***/ }),
/***/ "2d00":
/***/ (function(module, exports, __webpack_require__) {
var global = __webpack_require__("da84");
var userAgent = __webpack_require__("342f");
var process = global.process;
var versions = process && process.versions;
var v8 = versions && versions.v8;
var match, version;
if (v8) {
match = v8.split('.');
version = match[0] + match[1];
} else if (userAgent) {
match = userAgent.match(/Edge\/(\d+)/);
if (!match || match[1] >= 74) {
match = userAgent.match(/Chrome\/(\d+)/);
if (match) version = match[1];
}
}
module.exports = version && +version;
/***/ }),
/***/ "342f":
/***/ (function(module, exports, __webpack_require__) {
var getBuiltIn = __webpack_require__("d066");
module.exports = getBuiltIn('navigator', 'userAgent') || '';
/***/ }),
/***/ "35a1":
/***/ (function(module, exports, __webpack_require__) {
var classof = __webpack_require__("f5df");
var Iterators = __webpack_require__("3f8c");
var wellKnownSymbol = __webpack_require__("b622");
var ITERATOR = wellKnownSymbol('iterator');
module.exports = function (it) {
if (it != undefined) return it[ITERATOR]
|| it['@@iterator']
|| Iterators[classof(it)];
};
/***/ }),
/***/ "37e8":
/***/ (function(module, exports, __webpack_require__) {
var DESCRIPTORS = __webpack_require__("83ab");
var definePropertyModule = __webpack_require__("9bf2");
var anObject = __webpack_require__("825a");
var objectKeys = __webpack_require__("df75");
// `Object.defineProperties` method
// https://tc39.github.io/ecma262/#sec-object.defineproperties
module.exports = DESCRIPTORS ? Object.defineProperties : function defineProperties(O, Properties) {
anObject(O);
var keys = objectKeys(Properties);
var length = keys.length;
var index = 0;
var key;
while (length > index) definePropertyModule.f(O, key = keys[index++], Properties[key]);
return O;
};
/***/ }),
/***/ "3bbe":
/***/ (function(module, exports, __webpack_require__) {
var isObject = __webpack_require__("861d");
module.exports = function (it) {
if (!isObject(it) && it !== null) {
throw TypeError("Can't set " + String(it) + ' as a prototype');
} return it;
};
/***/ }),
/***/ "3ca3":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var charAt = __webpack_require__("6547").charAt;
var InternalStateModule = __webpack_require__("69f3");
var defineIterator = __webpack_require__("7dd0");
var STRING_ITERATOR = 'String Iterator';
var setInternalState = InternalStateModule.set;
var getInternalState = InternalStateModule.getterFor(STRING_ITERATOR);
// `String.prototype[@@iterator]` method
// https://tc39.github.io/ecma262/#sec-string.prototype-@@iterator
defineIterator(String, 'String', function (iterated) {
setInternalState(this, {
type: STRING_ITERATOR,
string: String(iterated),
index: 0
});
// `%StringIteratorPrototype%.next` method
// https://tc39.github.io/ecma262/#sec-%stringiteratorprototype%.next
}, function next() {
var state = getInternalState(this);
var string = state.string;
var index = state.index;
var point;
if (index >= string.length) return { value: undefined, done: true };
point = charAt(string, index);
state.index += point.length;
return { value: point, done: false };
});
/***/ }),
/***/ "3f8c":
/***/ (function(module, exports) {
module.exports = {};
/***/ }),
/***/ "4160":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var $ = __webpack_require__("23e7");
var forEach = __webpack_require__("17c2");
// `Array.prototype.forEach` method
// https://tc39.github.io/ecma262/#sec-array.prototype.foreach
$({ target: 'Array', proto: true, forced: [].forEach != forEach }, {
forEach: forEach
});
/***/ }),
/***/ "428f":
/***/ (function(module, exports, __webpack_require__) {
var global = __webpack_require__("da84");
module.exports = global;
/***/ }),
/***/ "44ad":
/***/ (function(module, exports, __webpack_require__) {
var fails = __webpack_require__("d039");
var classof = __webpack_require__("c6b6");
var split = ''.split;
// fallback for non-array-like ES3 and non-enumerable old V8 strings
module.exports = fails(function () {
// throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
// eslint-disable-next-line no-prototype-builtins
return !Object('z').propertyIsEnumerable(0);
}) ? function (it) {
return classof(it) == 'String' ? split.call(it, '') : Object(it);
} : Object;
/***/ }),
/***/ "44d2":
/***/ (function(module, exports, __webpack_require__) {
var wellKnownSymbol = __webpack_require__("b622");
var create = __webpack_require__("7c73");
var definePropertyModule = __webpack_require__("9bf2");
var UNSCOPABLES = wellKnownSymbol('unscopables');
var ArrayPrototype = Array.prototype;
// Array.prototype[@@unscopables]
// https://tc39.github.io/ecma262/#sec-array.prototype-@@unscopables
if (ArrayPrototype[UNSCOPABLES] == undefined) {
definePropertyModule.f(ArrayPrototype, UNSCOPABLES, {
configurable: true,
value: create(null)
});
}
// add a key to Array.prototype[@@unscopables]
module.exports = function (key) {
ArrayPrototype[UNSCOPABLES][key] = true;
};
/***/ }),
/***/ "44e7":
/***/ (function(module, exports, __webpack_require__) {
var isObject = __webpack_require__("861d");
var classof = __webpack_require__("c6b6");
var wellKnownSymbol = __webpack_require__("b622");
var MATCH = wellKnownSymbol('match');
// `IsRegExp` abstract operation
// https://tc39.github.io/ecma262/#sec-isregexp
module.exports = function (it) {
var isRegExp;
return isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : classof(it) == 'RegExp');
};
/***/ }),
/***/ "45fc":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var $ = __webpack_require__("23e7");
var $some = __webpack_require__("b727").some;
var arrayMethodIsStrict = __webpack_require__("a640");
var arrayMethodUsesToLength = __webpack_require__("ae40");
var STRICT_METHOD = arrayMethodIsStrict('some');
var USES_TO_LENGTH = arrayMethodUsesToLength('some');
// `Array.prototype.some` method
// https://tc39.github.io/ecma262/#sec-array.prototype.some
$({ target: 'Array', proto: true, forced: !STRICT_METHOD || !USES_TO_LENGTH }, {
some: function some(callbackfn /* , thisArg */) {
return $some(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
}
});
/***/ }),
/***/ "466d":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var fixRegExpWellKnownSymbolLogic = __webpack_require__("d784");
var anObject = __webpack_require__("825a");
var toLength = __webpack_require__("50c4");
var requireObjectCoercible = __webpack_require__("1d80");
var advanceStringIndex = __webpack_require__("8aa5");
var regExpExec = __webpack_require__("14c3");
// @@match logic
fixRegExpWellKnownSymbolLogic('match', 1, function (MATCH, nativeMatch, maybeCallNative) {
return [
// `String.prototype.match` method
// https://tc39.github.io/ecma262/#sec-string.prototype.match
function match(regexp) {
var O = requireObjectCoercible(this);
var matcher = regexp == undefined ? undefined : regexp[MATCH];
return matcher !== undefined ? matcher.call(regexp, O) : new RegExp(regexp)[MATCH](String(O));
},
// `RegExp.prototype[@@match]` method
// https://tc39.github.io/ecma262/#sec-regexp.prototype-@@match
function (regexp) {
var res = maybeCallNative(nativeMatch, regexp, this);
if (res.done) return res.value;
var rx = anObject(regexp);
var S = String(this);
if (!rx.global) return regExpExec(rx, S);
var fullUnicode = rx.unicode;
rx.lastIndex = 0;
var A = [];
var n = 0;
var result;
while ((result = regExpExec(rx, S)) !== null) {
var matchStr = String(result[0]);
A[n] = matchStr;
if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength(rx.lastIndex), fullUnicode);
n++;
}
return n === 0 ? null : A;
}
];
});
/***/ }),
/***/ "4840":
/***/ (function(module, exports, __webpack_require__) {
var anObject = __webpack_require__("825a");
var aFunction = __webpack_require__("1c0b");
var wellKnownSymbol = __webpack_require__("b622");
var SPECIES = wellKnownSymbol('species');
// `SpeciesConstructor` abstract operation
// https://tc39.github.io/ecma262/#sec-speciesconstructor
module.exports = function (O, defaultConstructor) {
var C = anObject(O).constructor;
var S;
return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? defaultConstructor : aFunction(S);
};
/***/ }),
/***/ "4930":
/***/ (function(module, exports, __webpack_require__) {
var fails = __webpack_require__("d039");
module.exports = !!Object.getOwnPropertySymbols && !fails(function () {
// Chrome 38 Symbol has incorrect toString conversion
// eslint-disable-next-line no-undef
return !String(Symbol());
});
/***/ }),
/***/ "498a":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var $ = __webpack_require__("23e7");
var $trim = __webpack_require__("58a8").trim;
var forcedStringTrimMethod = __webpack_require__("c8d2");
// `String.prototype.trim` method
// https://tc39.github.io/ecma262/#sec-string.prototype.trim
$({ target: 'String', proto: true, forced: forcedStringTrimMethod('trim') }, {
trim: function trim() {
return $trim(this);
}
});
/***/ }),
/***/ "4d63":
/***/ (function(module, exports, __webpack_require__) {
var DESCRIPTORS = __webpack_require__("83ab");
var global = __webpack_require__("da84");
var isForced = __webpack_require__("94ca");
var inheritIfRequired = __webpack_require__("7156");
var defineProperty = __webpack_require__("9bf2").f;
var getOwnPropertyNames = __webpack_require__("241c").f;
var isRegExp = __webpack_require__("44e7");
var getFlags = __webpack_require__("ad6d");
var stickyHelpers = __webpack_require__("9f7f");
var redefine = __webpack_require__("6eeb");
var fails = __webpack_require__("d039");
var setInternalState = __webpack_require__("69f3").set;
var setSpecies = __webpack_require__("2626");
var wellKnownSymbol = __webpack_require__("b622");
var MATCH = wellKnownSymbol('match');
var NativeRegExp = global.RegExp;
var RegExpPrototype = NativeRegExp.prototype;
var re1 = /a/g;
var re2 = /a/g;
// "new" should create a new object, old webkit bug
var CORRECT_NEW = new NativeRegExp(re1) !== re1;
var UNSUPPORTED_Y = stickyHelpers.UNSUPPORTED_Y;
var FORCED = DESCRIPTORS && isForced('RegExp', (!CORRECT_NEW || UNSUPPORTED_Y || fails(function () {
re2[MATCH] = false;
// RegExp constructor can alter flags and IsRegExp works correct with @@match
return NativeRegExp(re1) != re1 || NativeRegExp(re2) == re2 || NativeRegExp(re1, 'i') != '/a/i';
})));
// `RegExp` constructor
// https://tc39.github.io/ecma262/#sec-regexp-constructor
if (FORCED) {
var RegExpWrapper = function RegExp(pattern, flags) {
var thisIsRegExp = this instanceof RegExpWrapper;
var patternIsRegExp = isRegExp(pattern);
var flagsAreUndefined = flags === undefined;
var sticky;
if (!thisIsRegExp && patternIsRegExp && pattern.constructor === RegExpWrapper && flagsAreUndefined) {
return pattern;
}
if (CORRECT_NEW) {
if (patternIsRegExp && !flagsAreUndefined) pattern = pattern.source;
} else if (pattern instanceof RegExpWrapper) {
if (flagsAreUndefined) flags = getFlags.call(pattern);
pattern = pattern.source;
}
if (UNSUPPORTED_Y) {
sticky = !!flags && flags.indexOf('y') > -1;
if (sticky) flags = flags.replace(/y/g, '');
}
var result = inheritIfRequired(
CORRECT_NEW ? new NativeRegExp(pattern, flags) : NativeRegExp(pattern, flags),
thisIsRegExp ? this : RegExpPrototype,
RegExpWrapper
);
if (UNSUPPORTED_Y && sticky) setInternalState(result, { sticky: sticky });
return result;
};
var proxy = function (key) {
key in RegExpWrapper || defineProperty(RegExpWrapper, key, {
configurable: true,
get: function () { return NativeRegExp[key]; },
set: function (it) { NativeRegExp[key] = it; }
});
};
var keys = getOwnPropertyNames(NativeRegExp);
var index = 0;
while (keys.length > index) proxy(keys[index++]);
RegExpPrototype.constructor = RegExpWrapper;
RegExpWrapper.prototype = RegExpPrototype;
redefine(global, 'RegExp', RegExpWrapper);
}
// https://tc39.github.io/ecma262/#sec-get-regexp-@@species
setSpecies('RegExp');
/***/ }),
/***/ "4d64":
/***/ (function(module, exports, __webpack_require__) {
var toIndexedObject = __webpack_require__("fc6a");
var toLength = __webpack_require__("50c4");
var toAbsoluteIndex = __webpack_require__("23cb");
// `Array.prototype.{ indexOf, includes }` methods implementation
var createMethod = function (IS_INCLUDES) {
return function ($this, el, fromIndex) {
var O = toIndexedObject($this);
var length = toLength(O.length);
var index = toAbsoluteIndex(fromIndex, length);
var value;
// Array#includes uses SameValueZero equality algorithm
// eslint-disable-next-line no-self-compare
if (IS_INCLUDES && el != el) while (length > index) {
value = O[index++];
// eslint-disable-next-line no-self-compare
if (value != value) return true;
// Array#indexOf ignores holes, Array#includes - not
} else for (;length > index; index++) {
if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
} return !IS_INCLUDES && -1;
};
};
module.exports = {
// `Array.prototype.includes` method
// https://tc39.github.io/ecma262/#sec-array.prototype.includes
includes: createMethod(true),
// `Array.prototype.indexOf` method
// https://tc39.github.io/ecma262/#sec-array.prototype.indexof
indexOf: createMethod(false)
};
/***/ }),
/***/ "4de4":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var $ = __webpack_require__("23e7");
var $filter = __webpack_require__("b727").filter;
var arrayMethodHasSpeciesSupport = __webpack_require__("1dde");
var arrayMethodUsesToLength = __webpack_require__("ae40");
var HAS_SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('filter');
// Edge 14- issue
var USES_TO_LENGTH = arrayMethodUsesToLength('filter');
// `Array.prototype.filter` method
// https://tc39.github.io/ecma262/#sec-array.prototype.filter
// with adding support of @@species
$({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT || !USES_TO_LENGTH }, {
filter: function filter(callbackfn /* , thisArg */) {
return $filter(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
}
});
/***/ }),
/***/ "4df4":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var bind = __webpack_require__("0366");
var toObject = __webpack_require__("7b0b");
var callWithSafeIterationClosing = __webpack_require__("9bdd");
var isArrayIteratorMethod = __webpack_require__("e95a");
var toLength = __webpack_require__("50c4");
var createProperty = __webpack_require__("8418");
var getIteratorMethod = __webpack_require__("35a1");
// `Array.from` method implementation
// https://tc39.github.io/ecma262/#sec-array.from
module.exports = function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) {
var O = toObject(arrayLike);
var C = typeof this == 'function' ? this : Array;
var argumentsLength = arguments.length;
var mapfn = argumentsLength > 1 ? arguments[1] : undefined;
var mapping = mapfn !== undefined;
var iteratorMethod = getIteratorMethod(O);
var index = 0;
var length, result, step, iterator, next, value;
if (mapping) mapfn = bind(mapfn, argumentsLength > 2 ? arguments[2] : undefined, 2);
// if the target is not iterable or it's an array with the default iterator - use a simple case
if (iteratorMethod != undefined && !(C == Array && isArrayIteratorMethod(iteratorMethod))) {
iterator = iteratorMethod.call(O);
next = iterator.next;
result = new C();
for (;!(step = next.call(iterator)).done; index++) {
value = mapping ? callWithSafeIterationClosing(iterator, mapfn, [step.value, index], true) : step.value;
createProperty(result, index, value);
}
} else {
length = toLength(O.length);
result = new C(length);
for (;length > index; index++) {
value = mapping ? mapfn(O[index], index) : O[index];
createProperty(result, index, value);
}
}
result.length = index;
return result;
};
/***/ }),
/***/ "50c4":
/***/ (function(module, exports, __webpack_require__) {
var toInteger = __webpack_require__("a691");
var min = Math.min;
// `ToLength` abstract operation
// https://tc39.github.io/ecma262/#sec-tolength
module.exports = function (argument) {
return argument > 0 ? min(toInteger(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991
};
/***/ }),
/***/ "5135":
/***/ (function(module, exports) {
var hasOwnProperty = {}.hasOwnProperty;
module.exports = function (it, key) {
return hasOwnProperty.call(it, key);
};
/***/ }),
/***/ "5319":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var fixRegExpWellKnownSymbolLogic = __webpack_require__("d784");
var anObject = __webpack_require__("825a");
var toObject = __webpack_require__("7b0b");
var toLength = __webpack_require__("50c4");
var toInteger = __webpack_require__("a691");
var requireObjectCoercible = __webpack_require__("1d80");
var advanceStringIndex = __webpack_require__("8aa5");
var regExpExec = __webpack_require__("14c3");
var max = Math.max;
var min = Math.min;
var floor = Math.floor;
var SUBSTITUTION_SYMBOLS = /\$([$&'`]|\d\d?|<[^>]*>)/g;
var SUBSTITUTION_SYMBOLS_NO_NAMED = /\$([$&'`]|\d\d?)/g;
var maybeToString = function (it) {
return it === undefined ? it : String(it);
};
// @@replace logic
fixRegExpWellKnownSymbolLogic('replace', 2, function (REPLACE, nativeReplace, maybeCallNative, reason) {
var REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE = reason.REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE;
var REPLACE_KEEPS_$0 = reason.REPLACE_KEEPS_$0;
var UNSAFE_SUBSTITUTE = REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE ? '$' : '$0';
return [
// `String.prototype.replace` method
// https://tc39.github.io/ecma262/#sec-string.prototype.replace
function replace(searchValue, replaceValue) {
var O = requireObjectCoercible(this);
var replacer = searchValue == undefined ? undefined : searchValue[REPLACE];
return replacer !== undefined
? replacer.call(searchValue, O, replaceValue)
: nativeReplace.call(String(O), searchValue, replaceValue);
},
// `RegExp.prototype[@@replace]` method
// https://tc39.github.io/ecma262/#sec-regexp.prototype-@@replace
function (regexp, replaceValue) {
if (
(!REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE && REPLACE_KEEPS_$0) ||
(typeof replaceValue === 'string' && replaceValue.indexOf(UNSAFE_SUBSTITUTE) === -1)
) {
var res = maybeCallNative(nativeReplace, regexp, this, replaceValue);
if (res.done) return res.value;
}
var rx = anObject(regexp);
var S = String(this);
var functionalReplace = typeof replaceValue === 'function';
if (!functionalReplace) replaceValue = String(replaceValue);
var global = rx.global;
if (global) {
var fullUnicode = rx.unicode;
rx.lastIndex = 0;
}
var results = [];
while (true) {
var result = regExpExec(rx, S);
if (result === null) break;
results.push(result);
if (!global) break;
var matchStr = String(result[0]);
if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength(rx.lastIndex), fullUnicode);
}
var accumulatedResult = '';
var nextSourcePosition = 0;
for (var i = 0; i < results.length; i++) {
result = results[i];
var matched = String(result[0]);
var position = max(min(toInteger(result.index), S.length), 0);
var captures = [];
// NOTE: This is equivalent to
// captures = result.slice(1).map(maybeToString)
// but for some reason `nativeSlice.call(result, 1, result.length)` (called in
// the slice polyfill when slicing native arrays) "doesn't work" in safari 9 and
// causes a crash (https://pastebin.com/N21QzeQA) when trying to debug it.
for (var j = 1; j < result.length; j++) captures.push(maybeToString(result[j]));
var namedCaptures = result.groups;
if (functionalReplace) {
var replacerArgs = [matched].concat(captures, position, S);
if (namedCaptures !== undefined) replacerArgs.push(namedCaptures);
var replacement = String(replaceValue.apply(undefined, replacerArgs));
} else {
replacement = getSubstitution(matched, S, position, captures, namedCaptures, replaceValue);
}
if (position >= nextSourcePosition) {
accumulatedResult += S.slice(nextSourcePosition, position) + replacement;
nextSourcePosition = position + matched.length;
}
}
return accumulatedResult + S.slice(nextSourcePosition);
}
];
// https://tc39.github.io/ecma262/#sec-getsubstitution
function getSubstitution(matched, str, position, captures, namedCaptures, replacement) {
var tailPos = position + matched.length;
var m = captures.length;
var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED;
if (namedCaptures !== undefined) {
namedCaptures = toObject(namedCaptures);
symbols = SUBSTITUTION_SYMBOLS;
}
return nativeReplace.call(replacement, symbols, function (match, ch) {
var capture;
switch (ch.charAt(0)) {
case '$': return '$';
case '&': return matched;
case '`': return str.slice(0, position);
case "'": return str.slice(tailPos);
case '<':
capture = namedCaptures[ch.slice(1, -1)];
break;
default: // \d\d?
var n = +ch;
if (n === 0) return match;
if (n > m) {
var f = floor(n / 10);
if (f === 0) return match;
if (f <= m) return captures[f - 1] === undefined ? ch.charAt(1) : captures[f - 1] + ch.charAt(1);
return match;
}
capture = captures[n - 1];
}
return capture === undefined ? '' : capture;
});
}
});
/***/ }),
/***/ "5692":
/***/ (function(module, exports, __webpack_require__) {
var IS_PURE = __webpack_require__("c430");
var store = __webpack_require__("c6cd");
(module.exports = function (key, value) {
return store[key] || (store[key] = value !== undefined ? value : {});
})('versions', []).push({
version: '3.6.5',
mode: IS_PURE ? 'pure' : 'global',
copyright: '© 2020 Denis Pushkarev (zloirock.ru)'
});
/***/ }),
/***/ "56ef":
/***/ (function(module, exports, __webpack_require__) {
var getBuiltIn = __webpack_require__("d066");
var getOwnPropertyNamesModule = __webpack_require__("241c");
var getOwnPropertySymbolsModule = __webpack_require__("7418");
var anObject = __webpack_require__("825a");
// all object keys, includes non-enumerable and symbols
module.exports = getBuiltIn('Reflect', 'ownKeys') || function ownKeys(it) {
var keys = getOwnPropertyNamesModule.f(anObject(it));
var getOwnPropertySymbols = getOwnPropertySymbolsModule.f;
return getOwnPropertySymbols ? keys.concat(getOwnPropertySymbols(it)) : keys;
};
/***/ }),
/***/ "5899":
/***/ (function(module, exports) {
// a string of all valid unicode whitespaces
// eslint-disable-next-line max-len
module.exports = '\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF';
/***/ }),
/***/ "58a8":
/***/ (function(module, exports, __webpack_require__) {
var requireObjectCoercible = __webpack_require__("1d80");
var whitespaces = __webpack_require__("5899");
var whitespace = '[' + whitespaces + ']';
var ltrim = RegExp('^' + whitespace + whitespace + '*');
var rtrim = RegExp(whitespace + whitespace + '*$');
// `String.prototype.{ trim, trimStart, trimEnd, trimLeft, trimRight }` methods implementation
var createMethod = function (TYPE) {
return function ($this) {
var string = String(requireObjectCoercible($this));
if (TYPE & 1) string = string.replace(ltrim, '');
if (TYPE & 2) string = string.replace(rtrim, '');
return string;
};
};
module.exports = {
// `String.prototype.{ trimLeft, trimStart }` methods
// https://tc39.github.io/ecma262/#sec-string.prototype.trimstart
start: createMethod(1),
// `String.prototype.{ trimRight, trimEnd }` methods
// https://tc39.github.io/ecma262/#sec-string.prototype.trimend
end: createMethod(2),
// `String.prototype.trim` method
// https://tc39.github.io/ecma262/#sec-string.prototype.trim
trim: createMethod(3)
};
/***/ }),
/***/ "5a34":
/***/ (function(module, exports, __webpack_require__) {
var isRegExp = __webpack_require__("44e7");
module.exports = function (it) {
if (isRegExp(it)) {
throw TypeError("The method doesn't accept regular expressions");
} return it;
};
/***/ }),
/***/ "5c6c":
/***/ (function(module, exports) {
module.exports = function (bitmap, value) {
return {
enumerable: !(bitmap & 1),
configurable: !(bitmap & 2),
writable: !(bitmap & 4),
value: value
};
};
/***/ }),
/***/ "60da":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var DESCRIPTORS = __webpack_require__("83ab");
var fails = __webpack_require__("d039");
var objectKeys = __webpack_require__("df75");
var getOwnPropertySymbolsModule = __webpack_require__("7418");
var propertyIsEnumerableModule = __webpack_require__("d1e7");
var toObject = __webpack_require__("7b0b");
var IndexedObject = __webpack_require__("44ad");
var nativeAssign = Object.assign;
var defineProperty = Object.defineProperty;
// `Object.assign` method
// https://tc39.github.io/ecma262/#sec-object.assign
module.exports = !nativeAssign || fails(function () {
// should have correct order of operations (Edge bug)
if (DESCRIPTORS && nativeAssign({ b: 1 }, nativeAssign(defineProperty({}, 'a', {
enumerable: true,
get: function () {
defineProperty(this, 'b', {
value: 3,
enumerable: false
});
}
}), { b: 2 })).b !== 1) return true;
// should work with symbols and should have deterministic property order (V8 bug)
var A = {};
var B = {};
// eslint-disable-next-line no-undef
var symbol = Symbol();
var alphabet = 'abcdefghijklmnopqrst';
A[symbol] = 7;
alphabet.split('').forEach(function (chr) { B[chr] = chr; });
return nativeAssign({}, A)[symbol] != 7 || objectKeys(nativeAssign({}, B)).join('') != alphabet;
}) ? function assign(target, source) { // eslint-disable-line no-unused-vars
var T = toObject(target);
var argumentsLength = arguments.length;
var index = 1;
var getOwnPropertySymbols = getOwnPropertySymbolsModule.f;
var propertyIsEnumerable = propertyIsEnumerableModule.f;
while (argumentsLength > index) {
var S = IndexedObject(arguments[index++]);
var keys = getOwnPropertySymbols ? objectKeys(S).concat(getOwnPropertySymbols(S)) : objectKeys(S);
var length = keys.length;
var j = 0;
var key;
while (length > j) {
key = keys[j++];
if (!DESCRIPTORS || propertyIsEnumerable.call(S, key)) T[key] = S[key];
}
} return T;
} : nativeAssign;
/***/ }),
/***/ "6547":
/***/ (function(module, exports, __webpack_require__) {
var toInteger = __webpack_require__("a691");
var requireObjectCoercible = __webpack_require__("1d80");
// `String.prototype.{ codePointAt, at }` methods implementation
var createMethod = function (CONVERT_TO_STRING) {
return function ($this, pos) {
var S = String(requireObjectCoercible($this));
var position = toInteger(pos);
var size = S.length;
var first, second;
if (position < 0 || position >= size) return CONVERT_TO_STRING ? '' : undefined;
first = S.charCodeAt(position);
return first < 0xD800 || first > 0xDBFF || position + 1 === size
|| (second = S.charCodeAt(position + 1)) < 0xDC00 || second > 0xDFFF
? CONVERT_TO_STRING ? S.charAt(position) : first
: CONVERT_TO_STRING ? S.slice(position, position + 2) : (first - 0xD800 << 10) + (second - 0xDC00) + 0x10000;
};
};
module.exports = {
// `String.prototype.codePointAt` method
// https://tc39.github.io/ecma262/#sec-string.prototype.codepointat
codeAt: createMethod(false),
// `String.prototype.at` method
// https://github.com/mathiasbynens/String.prototype.at
charAt: createMethod(true)
};
/***/ }),
/***/ "65f0":
/***/ (function(module, exports, __webpack_require__) {
var isObject = __webpack_require__("861d");
var isArray = __webpack_require__("e8b5");
var wellKnownSymbol = __webpack_require__("b622");
var SPECIES = wellKnownSymbol('species');
// `ArraySpeciesCreate` abstract operation
// https://tc39.github.io/ecma262/#sec-arrayspeciescreate
module.exports = function (originalArray, length) {
var C;
if (isArray(originalArray)) {
C = originalArray.constructor;
// cross-realm fallback
if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined;
else if (isObject(C)) {
C = C[SPECIES];
if (C === null) C = undefined;
}
} return new (C === undefined ? Array : C)(length === 0 ? 0 : length);
};
/***/ }),
/***/ "69f3":
/***/ (function(module, exports, __webpack_require__) {
var NATIVE_WEAK_MAP = __webpack_require__("7f9a");
var global = __webpack_require__("da84");
var isObject = __webpack_require__("861d");
var createNonEnumerableProperty = __webpack_require__("9112");
var objectHas = __webpack_require__("5135");
var sharedKey = __webpack_require__("f772");
var hiddenKeys = __webpack_require__("d012");
var WeakMap = global.WeakMap;
var set, get, has;
var enforce = function (it) {
return has(it) ? get(it) : set(it, {});
};
var getterFor = function (TYPE) {
return function (it) {
var state;
if (!isObject(it) || (state = get(it)).type !== TYPE) {
throw TypeError('Incompatible receiver, ' + TYPE + ' required');
} return state;
};
};
if (NATIVE_WEAK_MAP) {
var store = new WeakMap();
var wmget = store.get;
var wmhas = store.has;
var wmset = store.set;
set = function (it, metadata) {
wmset.call(store, it, metadata);
return metadata;
};
get = function (it) {
return wmget.call(store, it) || {};
};
has = function (it) {
return wmhas.call(store, it);
};
} else {
var STATE = sharedKey('state');
hiddenKeys[STATE] = true;
set = function (it, metadata) {
createNonEnumerableProperty(it, STATE, metadata);
return metadata;
};
get = function (it) {
return objectHas(it, STATE) ? it[STATE] : {};
};
has = function (it) {
return objectHas(it, STATE);
};
}
module.exports = {
set: set,
get: get,
has: has,
enforce: enforce,
getterFor: getterFor
};
/***/ }),
/***/ "6eeb":
/***/ (function(module, exports, __webpack_require__) {
var global = __webpack_require__("da84");
var createNonEnumerableProperty = __webpack_require__("9112");
var has = __webpack_require__("5135");
var setGlobal = __webpack_require__("ce4e");
var inspectSource = __webpack_require__("8925");
var InternalStateModule = __webpack_require__("69f3");
var getInternalState = InternalStateModule.get;
var enforceInternalState = InternalStateModule.enforce;
var TEMPLATE = String(String).split('String');
(module.exports = function (O, key, value, options) {
var unsafe = options ? !!options.unsafe : false;
var simple = options ? !!options.enumerable : false;
var noTargetGet = options ? !!options.noTargetGet : false;
if (typeof value == 'function') {
if (typeof key == 'string' && !has(value, 'name')) createNonEnumerableProperty(value, 'name', key);
enforceInternalState(value).source = TEMPLATE.join(typeof key == 'string' ? key : '');
}
if (O === global) {
if (simple) O[key] = value;
else setGlobal(key, value);
return;
} else if (!unsafe) {
delete O[key];
} else if (!noTargetGet && O[key]) {
simple = true;
}
if (simple) O[key] = value;
else createNonEnumerableProperty(O, key, value);
// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
})(Function.prototype, 'toString', function toString() {
return typeof this == 'function' && getInternalState(this).source || inspectSource(this);
});
/***/ }),
/***/ "7156":
/***/ (function(module, exports, __webpack_require__) {
var isObject = __webpack_require__("861d");
var setPrototypeOf = __webpack_require__("d2bb");
// makes subclassing work correct for wrapped built-ins
module.exports = function ($this, dummy, Wrapper) {
var NewTarget, NewTargetPrototype;
if (
// it can work only with native `setPrototypeOf`
setPrototypeOf &&
// we haven't completely correct pre-ES6 way for getting `new.target`, so use this
typeof (NewTarget = dummy.constructor) == 'function' &&
NewTarget !== Wrapper &&
isObject(NewTargetPrototype = NewTarget.prototype) &&
NewTargetPrototype !== Wrapper.prototype
) setPrototypeOf($this, NewTargetPrototype);
return $this;
};
/***/ }),
/***/ "7418":
/***/ (function(module, exports) {
exports.f = Object.getOwnPropertySymbols;
/***/ }),
/***/ "746f":
/***/ (function(module, exports, __webpack_require__) {
var path = __webpack_require__("428f");
var has = __webpack_require__("5135");
var wrappedWellKnownSymbolModule = __webpack_require__("e538");
var defineProperty = __webpack_require__("9bf2").f;
module.exports = function (NAME) {
var Symbol = path.Symbol || (path.Symbol = {});
if (!has(Symbol, NAME)) defineProperty(Symbol, NAME, {
value: wrappedWellKnownSymbolModule.f(NAME)
});
};
/***/ }),
/***/ "7839":
/***/ (function(module, exports) {
// IE8- don't enum bug keys
module.exports = [
'constructor',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'toLocaleString',
'toString',
'valueOf'
];
/***/ }),
/***/ "7b0b":
/***/ (function(module, exports, __webpack_require__) {
var requireObjectCoercible = __webpack_require__("1d80");
// `ToObject` abstract operation
// https://tc39.github.io/ecma262/#sec-toobject
module.exports = function (argument) {
return Object(requireObjectCoercible(argument));
};
/***/ }),
/***/ "7c73":
/***/ (function(module, exports, __webpack_require__) {
var anObject = __webpack_require__("825a");
var defineProperties = __webpack_require__("37e8");
var enumBugKeys = __webpack_require__("7839");
var hiddenKeys = __webpack_require__("d012");
var html = __webpack_require__("1be4");
var documentCreateElement = __webpack_require__("cc12");
var sharedKey = __webpack_require__("f772");
var GT = '>';
var LT = '<';
var PROTOTYPE = 'prototype';
var SCRIPT = 'script';
var IE_PROTO = sharedKey('IE_PROTO');
var EmptyConstructor = function () { /* empty */ };
var scriptTag = function (content) {
return LT + SCRIPT + GT + content + LT + '/' + SCRIPT + GT;
};
// Create object with fake `null` prototype: use ActiveX Object with cleared prototype
var NullProtoObjectViaActiveX = function (activeXDocument) {
activeXDocument.write(scriptTag(''));
activeXDocument.close();
var temp = activeXDocument.parentWindow.Object;
activeXDocument = null; // avoid memory leak
return temp;
};
// Create object with fake `null` prototype: use iframe Object with cleared prototype
var NullProtoObjectViaIFrame = function () {
// Thrash, waste and sodomy: IE GC bug
var iframe = documentCreateElement('iframe');
var JS = 'java' + SCRIPT + ':';
var iframeDocument;
iframe.style.display = 'none';
html.appendChild(iframe);
// https://github.com/zloirock/core-js/issues/475
iframe.src = String(JS);
iframeDocument = iframe.contentWindow.document;
iframeDocument.open();
iframeDocument.write(scriptTag('document.F=Object'));
iframeDocument.close();
return iframeDocument.F;
};
// Check for document.domain and active x support
// No need to use active x approach when document.domain is not set
// see https://github.com/es-shims/es5-shim/issues/150
// variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346
// avoid IE GC bug
var activeXDocument;
var NullProtoObject = function () {
try {
/* global ActiveXObject */
activeXDocument = document.domain && new ActiveXObject('htmlfile');
} catch (error) { /* ignore */ }
NullProtoObject = activeXDocument ? NullProtoObjectViaActiveX(activeXDocument) : NullProtoObjectViaIFrame();
var length = enumBugKeys.length;
while (length--) delete NullProtoObject[PROTOTYPE][enumBugKeys[length]];
return NullProtoObject();
};
hiddenKeys[IE_PROTO] = true;
// `Object.create` method
// https://tc39.github.io/ecma262/#sec-object.create
module.exports = Object.create || function create(O, Properties) {
var result;
if (O !== null) {
EmptyConstructor[PROTOTYPE] = anObject(O);
result = new EmptyConstructor();
EmptyConstructor[PROTOTYPE] = null;
// add "__proto__" for Object.getPrototypeOf polyfill
result[IE_PROTO] = O;
} else result = NullProtoObject();
return Properties === undefined ? result : defineProperties(result, Properties);
};
/***/ }),
/***/ "7dd0":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var $ = __webpack_require__("23e7");
var createIteratorConstructor = __webpack_require__("9ed3");
var getPrototypeOf = __webpack_require__("e163");
var setPrototypeOf = __webpack_require__("d2bb");
var setToStringTag = __webpack_require__("d44e");
var createNonEnumerableProperty = __webpack_require__("9112");
var redefine = __webpack_require__("6eeb");
var wellKnownSymbol = __webpack_require__("b622");
var IS_PURE = __webpack_require__("c430");
var Iterators = __webpack_require__("3f8c");
var IteratorsCore = __webpack_require__("ae93");
var IteratorPrototype = IteratorsCore.IteratorPrototype;
var BUGGY_SAFARI_ITERATORS = IteratorsCore.BUGGY_SAFARI_ITERATORS;
var ITERATOR = wellKnownSymbol('iterator');
var KEYS = 'keys';
var VALUES = 'values';
var ENTRIES = 'entries';
var returnThis = function () { return this; };
modu
gitextract_knz350g7/
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE.md
├── MIGRATION.md
├── README.md
├── babel.config.js
├── demo/
│ ├── .gitignore
│ ├── README.md
│ ├── babel.config.js
│ ├── package.json
│ ├── public/
│ │ └── index.html
│ ├── src/
│ │ ├── App.vue
│ │ ├── assets/
│ │ │ ├── _variables.styl
│ │ │ └── demo.styl
│ │ ├── components/
│ │ │ ├── ConfigRow.vue
│ │ │ ├── OverlayPanel.vue
│ │ │ ├── Playground.vue
│ │ │ ├── SampleBlock.vue
│ │ │ └── Samples.vue
│ │ └── main.js
│ └── vue.config.js
├── dist/
│ ├── VueTimepicker.common.js
│ ├── VueTimepicker.css
│ ├── VueTimepicker.umd.js
│ └── demo.html
├── package.json
└── src/
├── index.js
└── vue-timepicker.vue
SYMBOL INDEX (20 symbols across 2 files)
FILE: dist/VueTimepicker.common.js
function __webpack_require__ (line 7) | function __webpack_require__(moduleId) {
function getSubstitution (line 1407) | function getSubstitution(matched, str, position, captures, namedCaptures...
function getCurrentScript (line 2132) | function getCurrentScript () {
function RE (line 2530) | function RE(s, f) {
function F (line 4150) | function F() { /* empty */ }
function _typeof (line 4468) | function _typeof(obj) {
function _arrayLikeToArray (line 4487) | function _arrayLikeToArray(arr, len) {
function _unsupportedIterableToArray (line 4504) | function _unsupportedIterableToArray(o, minLen) {
function _createForOfIteratorHelper (line 4521) | function _createForOfIteratorHelper(o) {
function normalizeComponent (line 7096) | function normalizeComponent (
FILE: dist/VueTimepicker.umd.js
function __webpack_require__ (line 16) | function __webpack_require__(moduleId) {
function getSubstitution (line 1416) | function getSubstitution(matched, str, position, captures, namedCaptures...
function getCurrentScript (line 2141) | function getCurrentScript () {
function RE (line 2539) | function RE(s, f) {
function F (line 4159) | function F() { /* empty */ }
function _typeof (line 4477) | function _typeof(obj) {
function _arrayLikeToArray (line 4496) | function _arrayLikeToArray(arr, len) {
function _unsupportedIterableToArray (line 4513) | function _unsupportedIterableToArray(o, minLen) {
function _createForOfIteratorHelper (line 4530) | function _createForOfIteratorHelper(o) {
function normalizeComponent (line 7105) | function normalizeComponent (
Condensed preview — 29 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (742K chars).
[
{
"path": ".gitignore",
"chars": 905,
"preview": "# Compiled source #\n###################\n*.com\n*.class\n*.dll\n*.exe\n*.o\n*.so\n\n# Packages #\n############\n*.7z\n*.dmg\n*.gz\n*."
},
{
"path": "CHANGELOG.md",
"chars": 7576,
"preview": "# CHANGELOG\n\n> The Change Log of Vue2 Timepicker `vue2-timepicker`\n\n## v 1.1.6\n\n### New\n\n- Support appending the dropdow"
},
{
"path": "CONTRIBUTING.md",
"chars": 1432,
"preview": "# Contribution\n\nPlease feel free to fork and help developing.\n\n```bash\n# Install dependencies\nyarn install\n\n# Init devel"
},
{
"path": "LICENSE.md",
"chars": 1069,
"preview": "MIT License\n\nCopyright (c) 2019 Phoenix Wong\n\nPermission is hereby granted, free of charge, to any person obtaining a co"
},
{
"path": "MIGRATION.md",
"chars": 4060,
"preview": "# Table of Contents\n\n- [Migrating from Vue 1.x vue-timepicker](https://github.com/phoenixwong/vue2-timepicker/blob/maste"
},
{
"path": "README.md",
"chars": 31680,
"preview": "# Vue2 Timepicker \n\n\n$vue-dark = #35495E\n$vue-darker = darken($vue-dark, 25%)"
},
{
"path": "demo/src/assets/demo.styl",
"chars": 3852,
"preview": "@import './_variables.styl'\n\nbody,\nhtml\n margin: 0\n padding: 0\n font-family: sans-serif\n color: $body-color\n -webki"
},
{
"path": "demo/src/components/ConfigRow.vue",
"chars": 1191,
"preview": "<script>\nexport default {\n name: 'ConfigRow',\n props: {\n label: { type: String },\n isGroup: { type: Boolean, def"
},
{
"path": "demo/src/components/OverlayPanel.vue",
"chars": 2091,
"preview": "<script>\nexport default {\n name: 'OverlayPanel',\n props: {\n title: { type: String }\n },\n methods: {\n closePane"
},
{
"path": "demo/src/components/Playground.vue",
"chars": 32501,
"preview": "<script>\nimport VueTimepicker from '../../../src/vue-timepicker'\nimport ConfigRow from './ConfigRow'\nimport OverlayPanel"
},
{
"path": "demo/src/components/SampleBlock.vue",
"chars": 1013,
"preview": "<script>\nexport default {\n name: 'SampleBlock',\n props: {\n id: { type: String }\n },\n computed: {\n blockHerf ()"
},
{
"path": "demo/src/components/Samples.vue",
"chars": 41789,
"preview": "<script>\nimport VueTimepicker from '../../../src/vue-timepicker'\nimport SampleBlock from './SampleBlock'\n\nexport default"
},
{
"path": "demo/src/main.js",
"chars": 545,
"preview": "import Vue from 'vue'\n\nimport VueHighlightJS from 'vue-highlight.js'\nimport javascript from 'highlight.js/lib/languages/"
},
{
"path": "demo/vue.config.js",
"chars": 137,
"preview": "module.exports = {\n outputDir: '../gh-pages',\n publicPath: process.env.NODE_ENV === 'production'\n ? '/vue2-timepick"
},
{
"path": "dist/VueTimepicker.common.js",
"chars": 242930,
"preview": "module.exports =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installed"
},
{
"path": "dist/VueTimepicker.css",
"chars": 5102,
"preview": ".vue__time-picker{display:inline-block;position:relative;font-size:1em;width:10em;font-family:sans-serif;vertical-align:"
},
{
"path": "dist/VueTimepicker.umd.js",
"chars": 243332,
"preview": "(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object"
},
{
"path": "dist/demo.html",
"chars": 204,
"preview": "<meta charset=\"utf-8\">\n<title>VueTimepicker demo</title>\n<script src=\"./VueTimepicker.umd.js\"></script>\n\n<link rel=\"styl"
},
{
"path": "package.json",
"chars": 1863,
"preview": "{\n \"name\": \"vue2-timepicker\",\n \"version\": \"1.1.6\",\n \"description\": \"A dropdown time picker (hour|minute|second) for V"
},
{
"path": "src/index.js",
"chars": 78,
"preview": "import VueTimepicker from './vue-timepicker.vue'\nexport default VueTimepicker\n"
},
{
"path": "src/vue-timepicker.vue",
"chars": 81317,
"preview": "<script>\nconst CONFIG = {\n HOUR_TOKENS: ['HH', 'H', 'hh', 'h', 'kk', 'k'],\n MINUTE_TOKENS: ['mm', 'm'],\n SECOND_TOKEN"
}
]
About this extraction
This page contains the full source code of the phoenixwong/vue2-timepicker GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 29 files (694.3 KB), approximately 183.2k tokens, and a symbol index with 20 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.