├── .babelrc
├── .eslintrc
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── dist
└── vue-ip-input.min.js
├── example
└── index.html
├── index.html
├── index.js
├── karma.config.js
├── package.json
├── src
├── index.js
└── vue-ip-input.vue
├── test
├── index.js
└── vue-ip-input.spec.js
├── webpack.base.config.js
├── webpack.dev.config.js
└── webpack.prod.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015"]
3 | }
4 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "eslint-config-google",
3 | "plugins": [
4 | "html"
5 | ],
6 | "rules": {
7 | "indent": [2, 4],
8 | "semi": [2, 'always'],
9 | "no-negated-condition": 0,
10 | "eqeqeq": [2, 'allow-null'],
11 | "no-eq-null": 0,
12 | "quote-props": [2, 'as-needed'],
13 | "no-new": 0
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # node module #
2 | node_modules/
3 |
4 | # test coveage result #
5 | coverage/
6 |
7 | .DS_Store
8 |
9 | # log file #
10 | *.log
11 |
12 | .idea
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - 6.3.0
4 | script:
5 | - npm run ci
6 | branches:
7 | only:
8 | - next
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 LinBin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-ip-input
2 | [](https://travis-ci.org/lakb248/vue-ip-input)
3 | [](https://codecov.io/gh/lakb248/vue-ip-input)
4 |
5 | > An ip input implement by vue 2.0
6 |
7 | ## Demo
8 |
9 | [Demo](https://lakb248.github.io/vue-ip-input)
10 |
11 | ## Usage
12 |
13 | ### Install
14 |
15 | ```bash
16 | npm install vue-ip-input --save
17 | ```
18 |
19 | ### CommonJS
20 |
21 | ```javascript
22 | var VueIpInput = require('vue-ip-input');
23 |
24 | new Vue({
25 | components: {
26 | 'vue-ip-input': VueIpInput
27 | },
28 | data: function () {
29 | return {
30 | ip: '127.0.0.1'
31 | };
32 | },
33 | methods: {
34 | onIpChange: function(ip) {
35 | console.log('ip input change:', ip);
36 | },
37 | onIpBlur: function (ip) {
38 | console.log('ip input blur:', ip);
39 | }
40 | },
41 | template: ''
42 | });
43 | ```
44 |
45 | ### ES6
46 | ```javascript
47 | import VueIpInput from 'vue-ip-input';
48 |
49 | new Vue({
50 | components: {
51 | 'vue-ip-input': VueIpInput
52 | },
53 | data() {
54 | return {
55 | ip: '127.0.0.1'
56 | };
57 | },
58 | methods: {
59 | onIpChange(ip) {
60 | console.log('ip input change:', ip);
61 | },
62 | onIpBlur(ip) {
63 | console.log('ip input blur:', ip);
64 | }
65 | },
66 | template: ''
67 | })
68 | ```
69 |
70 | ### Props
71 | | Property | Description |
72 | |:--|:--|
73 | | ip | the value of ip input |
74 | | onChange | trigger when the ip change |
75 | | onBlur | trigger when the input blur |
76 |
77 | ## Contribution
78 | First, install dependencies
79 | ```
80 | npm install
81 | ```
82 | Second, setup development environment
83 | ```
84 | npm run dev
85 | ```
86 |
87 | ## License
88 |
89 | [MIT](http://opensource.org/licenses/MIT)
90 |
--------------------------------------------------------------------------------
/dist/vue-ip-input.min.js:
--------------------------------------------------------------------------------
1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.VueIpInput=t():e.VueIpInput=t()}(this,function(){return function(e){function t(o){if(n[o])return n[o].exports;var i=n[o]={i:o,l:!1,exports:{}};return e[o].call(i.exports,i,i.exports,t),i.l=!0,i.exports}var n={};return t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:o})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=1)}([function(e,t,n){var o,i,r={};n(7),o=n(2),Object.keys(o).some(function(e){return"default"!==e&&"__esModule"!==e})&&console.warn("[vue-loader] src/vue-ip-input.vue: named exports in *.vue files are ignored."),i=n(5),e.exports=o||{},e.exports.__esModule&&(e.exports=e.exports.default);var s="function"==typeof e.exports?e.exports.options||(e.exports.options={}):e.exports;i&&(s.template=i),s.computed||(s.computed={}),Object.keys(r).forEach(function(e){var t=r[e];s.computed[e]=function(){return t}})},function(e,t,n){"use strict";var o=n(0),i=function(e){return e&&e.__esModule?e:{default:e}}(o);e.exports=i.default},function(e,t,n){"use strict";function o(e){var t,n,o,i,r,s={};return e.setSelectionRange?(s.begin=e.selectionStart,s.end=e.selectionEnd,s.result=e.value.substring(s.begin,s.end)):document.selection&&("input"===e.tagName.toLowerCase()?(t=document.selection.createRange(),n=e.createTextRange(),n.collapse(!0),n.select(),o=document.selection.createRange(),o.setEndPoint("EndToEnd",t),s.begin=o.text.length-t.text.length,s.end=o.text.length,s.result=t.text,t.select()):"textarea"===e.tagName.toLowerCase()&&(i=document.selection.createRange(),r=i.duplicate(),r.moveToElementText(e),r.setEndPoint("EndToEnd",i),s.begin=r.text.length-i.text.length,s.end=r.text.length,s.result=i.text)),e.focus(),s}Object.defineProperty(t,"__esModule",{value:!0}),t.default={props:{ip:{type:String,required:!0},placeholder:String,onChange:Function,onBlur:Function},data:function(){return{segments:["","","",""]}},watch:{ip:function(e){this.syncIp(e)}},methods:{onInputKeydown:function(e,t){var n=e.keyCode||e.which,i=e.target.value;8===n||37===n?(0===i.length||0===o(e.target).end)&&t>0&&(this.$el.getElementsByTagName("input")[t-1].focus(),e.preventDefault()):39===n&&o(e.target).end===i.length&&t<3&&this.$el.getElementsByTagName("input")[t+1].focus()},onInput:function(e,t){var n=e.target.value;e.target.value=this.segments[t];var o=Number(n);isNaN(o)||(""===n?this.segments.splice(t,1,""):o>255||o<0?this.segments.splice(t,1,255):this.segments.splice(t,1,o),(3===n.length&&t<3||"."===n[n.length-1])&&this.$el.getElementsByTagName("input")[t+1].focus())},onInputBlur:function(){var e=this;setTimeout(function(){-1===document.activeElement.className.indexOf("ip-segment-input")&&e.onBlur&&e.onBlur(e.segments.join("."))},50)},onPaste:function(e,t){var n=this;e.clipboardData.getData("text/plain").split(".").forEach(function(e,o){t+o<4&&!isNaN(e)&&e>=0&&e<=255&&n.segments.splice(t+o,1,e)}),e.preventDefault()},syncIp:function(e){var t=this;e&&-1!==e.indexOf(".")&&e.split(".").map(function(e,n){return(isNaN(e)||e<0||e>255)&&(e=255),t.segments.splice(n,1,e),e})}},mounted:function(){var e=this;this.syncIp(this.ip),this.$watch(function(){return e.segments.join(".")},function(t,n){t!==n&&("..."===t&&(t=""),e.onChange&&e.onChange(t))})}}},function(e,t,n){t=e.exports=n(4)(),t.push([e.i,".ip-input-container[_v-312b3ab3] {\n display: inline-block;\n height: 28px;\n line-height: normal;\n border: 1px solid #ccc;\n box-sizing: border-box;\n background-color: #fff; }\n\n.ip-segment[_v-312b3ab3] {\n display: inline-block;\n width: 39px;\n height: 26px;\n line-height: normal; }\n .ip-segment input[_v-312b3ab3] {\n width: 30px;\n height: 26px;\n line-height: normal;\n border: none;\n outline: none;\n text-align: center;\n text-indent: 0px;\n margin: 0px;\n padding: 0px;\n background-color: transparent; }\n .ip-segment i[_v-312b3ab3] {\n display: inline-block;\n font-size: 18px; }\n",""])},function(e,t){e.exports=function(){var e=[];return e.toString=function(){for(var e=[],t=0;t\n \n \n .\n
\n\n'},function(e,t){function n(e,t){for(var n=0;n=0&&v.splice(t,1)}function s(e){var t=document.createElement("style");return t.type="text/css",i(e,t),t}function a(e,t){var n,o,i;if(t.singleton){var a=g++;n=h||(h=s(t)),o=u.bind(null,n,a,!1),i=u.bind(null,n,a,!0)}else n=s(t),o=l.bind(null,n),i=function(){r(n)};return o(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;o(e=t)}else i()}}function u(e,t,n,o){var i=n?"":o.css;if(e.styleSheet)e.styleSheet.cssText=m(t,i);else{var r=document.createTextNode(i),s=e.childNodes;s[t]&&e.removeChild(s[t]),s.length?e.insertBefore(r,s[t]):e.appendChild(r)}}function l(e,t){var n=t.css,o=t.media,i=t.sourceMap;if(o&&e.setAttribute("media",o),i&&(n+="\n/*# sourceURL="+i.sources[0]+" */",n+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(i))))+" */"),e.styleSheet)e.styleSheet.cssText=n;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(n))}}var c={},p=function(e){var t;return function(){return void 0===t&&(t=e.apply(this,arguments)),t}},d=p(function(){return/msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase())}),f=p(function(){return document.head||document.getElementsByTagName("head")[0]}),h=null,g=0,v=[];e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");t=t||{},void 0===t.singleton&&(t.singleton=d()),void 0===t.insertAt&&(t.insertAt="bottom");var i=o(e);return n(i,t),function(e){for(var r=[],s=0;s
2 |
3 |
4 |
5 | Vue Ip Input
6 |
7 |
8 |
9 |
10 |
Result: {{ip}}
11 |
Change Event:
12 |
13 | - {{event.timestamp}}: {{event.val}}
14 |
15 |
Blur Event:
16 |
17 | - {{event.timestamp}}: {{event.val}}
18 |
19 |
20 |
21 |
22 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Vue Component
6 |
7 |
8 |
9 |
10 |
IP: {{ip}}
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import vueIpInput from './src/vue-ip-input.vue';
3 |
4 | new Vue({
5 | el: '#container',
6 | components: {
7 | 'vue-ip-input': vueIpInput
8 | },
9 | data() {
10 | return {
11 | ip: '127.0.0.1'
12 | };
13 | },
14 | methods: {
15 | ipChange(ip) {
16 | this.ip = ip;
17 | },
18 | changeIp() {
19 | this.ip = '1.1.1.1';
20 | }
21 | }
22 | });
23 |
--------------------------------------------------------------------------------
/karma.config.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var baseConfig = require('./webpack.base.config');
3 | var merge = require('webpack-merge');
4 | delete baseConfig.entry;
5 | console.log(baseConfig);
6 | baseConfig.entry = './test/index.js';
7 |
8 | // add isparta-loader to vue file
9 | var webpackConfig = baseConfig;
10 | webpackConfig.plugins = (baseConfig.plugins || []).concat([
11 | new webpack.LoaderOptionsPlugin({
12 | options: {
13 | vue: {
14 | loaders: {
15 | js: 'isparta-loader'
16 | }
17 | }
18 | }
19 | })
20 | ]);
21 |
22 | module.exports = function(config) {
23 | config.set({
24 | browsers: ['PhantomJS'],
25 | frameworks: ['jasmine'],
26 | reporters: ['progress', 'coverage', 'verbose'],
27 | // this is the entry file for all our tests.
28 | files: ['./test/index.js'],
29 | // we will pass the entry file to webpack for bundling.
30 | preprocessors: {
31 | './test/index.js': ['webpack']
32 | },
33 | coverageReporter: {
34 | dir: './coverage',
35 | reporters: [
36 | {type: 'html'},
37 | {type: 'text-summary'},
38 | {type: 'cobertura', subdir: '.'}
39 | ]
40 | },
41 | webpack: webpackConfig,
42 | webpackMiddleware: {
43 | noInfo: true
44 | },
45 | singleRun: true
46 | });
47 | };
48 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-ip-input",
3 | "version": "2.0.2",
4 | "description": "An ip input implement by vue 2.0",
5 | "main": "./dist/vue-ip-input.min.js",
6 | "scripts": {
7 | "dev": "webpack-dev-server --watch --progress --config webpack.dev.config.js --port 8888",
8 | "build": "webpack --progress --config webpack.prod.config.js",
9 | "test": "karma start karma.config.js",
10 | "ci": "npm run test && npm run build && codecov -t 4f1b7b5a-9eb3-41f5-9218-08b805826905 coverage/cobertura-coverage.xml"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "https://github.com/lakb248/vue-ip-input.git"
15 | },
16 | "bugs": {
17 | "url": "https://github.com/lakb248/vue-ip-input/issues"
18 | },
19 | "keywords": [
20 | "vue-component",
21 | "vuejs",
22 | "ip",
23 | "ip-input"
24 | ],
25 | "author": "lakb248@gmail.com",
26 | "license": "ISC",
27 | "dependencies": {
28 | "vue": "^2.0.1"
29 | },
30 | "devDependencies": {
31 | "babel-core": "^6.5.2",
32 | "babel-loader": "^6.2.2",
33 | "babel-plugin-transform-runtime": "^6.5.2",
34 | "babel-preset-es2015": "^6.5.0",
35 | "babel-runtime": "^6.9.2",
36 | "codecov": "^1.0.1",
37 | "css-loader": "^0.23.1",
38 | "eslint": "^3.1.1",
39 | "eslint-config-google": "^0.6.0",
40 | "eslint-config-vue": "^1.0.3",
41 | "eslint-plugin-html": "^1.5.1",
42 | "file-loader": "^0.8.5",
43 | "isparta": "^4.0.0",
44 | "isparta-loader": "^2.0.0",
45 | "istanbul": "^0.4.4",
46 | "jasmine-core": "^2.4.1",
47 | "karma": "^1.2.0",
48 | "karma-babel-preprocessor": "^6.0.1",
49 | "karma-coverage": "^1.1.1",
50 | "karma-html-reporter": "^0.2.7",
51 | "karma-jasmine": "^1.0.2",
52 | "karma-phantomjs-launcher": "^1.0.1",
53 | "karma-spec-reporter": "0.0.26",
54 | "karma-verbose-reporter": "0.0.3",
55 | "karma-webpack": "^1.8.0",
56 | "node-sass": "^3.4.2",
57 | "phantomjs": "^2.1.7",
58 | "sass-loader": "^3.1.2",
59 | "style-loader": "^0.13.0",
60 | "url-loader": "^0.5.7",
61 | "vue-hot-reload-api": "^1.3.2",
62 | "vue-html-loader": "^1.1.0",
63 | "vue-loader": "^8.1.3",
64 | "vue-style-loader": "^1.0.0",
65 | "webpack": "^2.1.0-beta.2",
66 | "webpack-dev-server": "^1.15.0",
67 | "webpack-merge": "^0.14.1"
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import vueIpInput from './vue-ip-input.vue';
2 |
3 | module.exports = vueIpInput;
4 |
--------------------------------------------------------------------------------
/src/vue-ip-input.vue:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
171 |
172 |
204 |
--------------------------------------------------------------------------------
/test/index.js:
--------------------------------------------------------------------------------
1 | // Polyfill fn.bind() for PhantomJS
2 | /* eslint-disable no-extend-native */
3 | // Function.prototype.bind = require('function-bind');
4 |
5 | // require all test files (files that ends with .spec.js)
6 | var testsContext = require.context('.', true, /\.spec$/);
7 | testsContext.keys().forEach(testsContext);
8 |
--------------------------------------------------------------------------------
/test/vue-ip-input.spec.js:
--------------------------------------------------------------------------------
1 | /* global document, describe, it, expect */
2 | import Vue from 'vue';
3 | import IpInput from '../src/vue-ip-input.vue';
4 |
5 | var initIpInput = config => {
6 | var comp = new Vue({
7 | template: '
',
10 | components: {
11 | 'vue-ip-input': IpInput
12 | },
13 | data() {
14 | return {
15 | ip: config.ip
16 | };
17 | },
18 | methods: {
19 | onChange(ip) {
20 | if (config.onChange) {
21 | config.onChange(ip);
22 | }
23 | },
24 | onBlur(ip) {
25 | if (config.onBlur) {
26 | config.onBlur(ip);
27 | }
28 | }
29 | }
30 | }).$mount();
31 | document.body.appendChild(comp.$el);
32 | return comp;
33 | };
34 |
35 | var trigger = (target, event, process) => {
36 | var e = document.createEvent('HTMLEvents');
37 | e.initEvent(event, true, true);
38 | if (process) process(e);
39 | target.dispatchEvent(e);
40 | return e;
41 | };
42 |
43 | describe('vue-ip-input.vue', () => {
44 | it('should have correct default ip', () => {
45 | expect(IpInput.data().segments.join(',')).toBe(',,,');
46 | });
47 |
48 | it('should render correct ip', () => {
49 | var vm = initIpInput({
50 | ip: '127.0.0.1'
51 | });
52 | expect(vm.$refs['ip-input'].segments.join('.')).toBe('127.0.0.1');
53 | });
54 |
55 | it('should render correct if the ip is invalid', () => {
56 | var vm = initIpInput({
57 | ip: '333.123.123.123'
58 | });
59 | expect(vm.$refs['ip-input'].segments.join('.')).toBe('255.123.123.123');
60 | });
61 | it('should update the ip if the input change', done => {
62 | var vm = initIpInput({
63 | ip: '127.0.0.1',
64 | onChange(ip) {
65 | vm.ip = ip;
66 | }
67 | });
68 | vm.$refs['ip-input'].segments.splice(0, 1, 255);
69 | Vue.nextTick(() => {
70 | expect(vm.ip).toBe('255.0.0.1');
71 | done();
72 | });
73 | });
74 | it('should update the ip to empty string if the input is epmty', done => {
75 | var vm = initIpInput({
76 | ip: '127.0.0.1',
77 | onChange(ip) {
78 | vm.ip = ip;
79 | }
80 | });
81 | var segments = vm.$refs['ip-input'].segments;
82 | segments.splice(0, 1, '');
83 | segments.splice(1, 1, '');
84 | segments.splice(2, 1, '');
85 | segments.splice(3, 1, '');
86 | Vue.nextTick(() => {
87 | expect(vm.ip).toBe('');
88 | done();
89 | });
90 | });
91 | it('should call onChange if the input is changed', done => {
92 | var onChangeCalled = false;
93 | var vm = initIpInput({
94 | ip: '127.0.0.1',
95 | onChange: () => {
96 | onChangeCalled = true;
97 | }
98 | });
99 | var segments = vm.$refs['ip-input'].segments;
100 | segments.splice(0, 1, '');
101 | Vue.nextTick(() => {
102 | expect(onChangeCalled).toBe(true);
103 | done();
104 | });
105 | });
106 | it('should call onBlur if the input is blur', done => {
107 | var onBlurCalled = false;
108 | var vm = initIpInput({
109 | ip: '127.0.0.1',
110 | onBlur: () => {
111 | onBlurCalled = true;
112 | }
113 | });
114 | var input = vm.$refs['ip-input'].$el.querySelector('input');
115 | input.focus();
116 | input.blur();
117 | Vue.nextTick(() => {
118 | setTimeout(() => {
119 | expect(onBlurCalled).toBe(true);
120 | done();
121 | }, 100);
122 | });
123 | });
124 | it('should update the ip if keydown(Number 2)', done => {
125 | var vm = initIpInput({
126 | ip: '127.0.0.1',
127 | onChange(ip) {
128 | vm.ip = ip;
129 | }
130 | });
131 | var ipInput = vm.$refs['ip-input'];
132 | var input = ipInput.$el.querySelectorAll('input')[1];
133 | input.value = '2';
134 | trigger(input, 'input');
135 | Vue.nextTick(() => {
136 | expect(vm.ip).toBe('127.2.0.1');
137 | done();
138 | });
139 | });
140 | it('should prevent the event if incorrect keydown(Alphabat a)', done => {
141 | var vm = initIpInput({
142 | ip: '0.0.0.1'
143 | });
144 | var ipInput = vm.$refs['ip-input'];
145 | var input = ipInput.$el.querySelector('input');
146 | input.value = 'a';
147 | trigger(input, 'input');
148 | Vue.nextTick(() => {
149 | expect(vm.ip).toBe('0.0.0.1');
150 | done();
151 | });
152 | });
153 | it('should set to 255 if the input is over 255', done => {
154 | var vm = initIpInput({
155 | ip: '0.0.0.1',
156 | onChange(ip) {
157 | vm.ip = ip;
158 | }
159 | });
160 | var ipInput = vm.$refs['ip-input'];
161 | var input = ipInput.$el.querySelector('input');
162 | input.value = '256';
163 | trigger(input, 'input');
164 | Vue.nextTick(() => {
165 | expect(vm.ip).toBe('255.0.0.1');
166 | done();
167 | });
168 | });
169 | it('should set to empty if the input is 0', done => {
170 | var vm = initIpInput({
171 | ip: '0.0.0.1',
172 | onChange(ip) {
173 | vm.ip = ip;
174 | }
175 | });
176 | var ipInput = vm.$refs['ip-input'];
177 | var input = ipInput.$el.querySelector('input');
178 | input.value = '0';
179 | trigger(input, 'input');
180 | Vue.nextTick(() => {
181 | expect(vm.ip).toBe('0.0.0.1');
182 | done();
183 | });
184 | });
185 | it('should move the cursor to previous' +
186 | 'input if left arrow is pressed', done => {
187 | var vm = initIpInput({
188 | ip: '0..0.1'
189 | });
190 | var ipInput = vm.$refs['ip-input'];
191 | var input = ipInput.$el.querySelectorAll('input')[1];
192 | trigger(input, 'keydown', e => {
193 | e.keyCode = 37;
194 | });
195 | Vue.nextTick(() => {
196 | expect(document.activeElement)
197 | .toBe(ipInput.$el.querySelector('input'));
198 | done();
199 | });
200 | });
201 | it('should move the cursor to next' +
202 | 'input if right arrow is pressed', done => {
203 | var vm = initIpInput({
204 | ip: '...'
205 | });
206 | var ipInput = vm.$refs['ip-input'];
207 | var input = ipInput.$el.querySelectorAll('input')[0];
208 | trigger(input, 'keydown', e => {
209 | e.keyCode = 39;
210 | });
211 | Vue.nextTick(() => {
212 | expect(document.activeElement)
213 | .toBe(ipInput.$el.querySelectorAll('input')[1]);
214 | done();
215 | });
216 | });
217 | });
218 |
--------------------------------------------------------------------------------
/webpack.base.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file webpack base config file
3 | */
4 |
5 | module.exports = {
6 | module: {
7 | loaders: [{
8 | test: /\.js$/,
9 | loader: 'babel-loader',
10 | exclude: /node_modules/
11 | }, {
12 | test: /\.vue$/,
13 | loader: 'vue-loader'
14 | }]
15 | },
16 | resolve: {
17 | alias: {
18 | vue: 'vue/dist/vue.js'
19 | }
20 | }
21 | };
22 |
--------------------------------------------------------------------------------
/webpack.dev.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file webpack dev config file
3 | */
4 | var config = require('./webpack.base.config');
5 | var path = require('path');
6 |
7 | config.entry = './index.js';
8 | config.output = {
9 | path: path.resolve('build') + '/',
10 | publicPath: 'build',
11 | filename: 'build.js'
12 | };
13 |
14 | module.exports = config;
15 |
--------------------------------------------------------------------------------
/webpack.prod.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file webpack prod config file
3 | */
4 | var webpack = require('webpack');
5 | var config = require('./webpack.base.config');
6 | var path = require('path');
7 |
8 | config.entry = './src/index.js';
9 | config.output = {
10 | path: path.resolve('dist') + '/',
11 | filename: 'vue-ip-input.min.js',
12 | library: 'VueIpInput',
13 | libraryTarget: 'umd'
14 | };
15 |
16 | config.plugins = (config.plugins || []).concat([
17 | new webpack.optimize.UglifyJsPlugin({
18 | sourceMap: false,
19 | compress: {
20 | warnings: false
21 | }
22 | })
23 | ]);
24 | module.exports = config;
25 |
--------------------------------------------------------------------------------