原生JS封装拖动验证滑块你会吗?「实践」
suiw9 2024-11-04 15:26 23 浏览 0 评论
作者:_release
转发链接:https://juejin.im/post/5ed37a73e51d45788c739784
前言
星期六闲着没事,就想着写写原生js玩玩,在网上看了几个效果后决定做这个效果,并且使用了prototype和eventEmitter封装成了库。
最终效果
分析
看到这个效果我们首先应该想到和拖动有关的api: onmousedown, onmousemove, onmouseup
其次要支持用户传入放置这个组件的dom元素和完成的回调事件。
最终如何使用?
我们先来看下使用方式,再来决定我们怎么编写这个库
具体使用就是这样的,我们还想用户能通过import等方式使用,所以我们就要支持esMoudule的导入方式。
编写库的整体初始框架
(function () {
// =================代码块1=========================================
var root = (typeof self == 'object' && self.self == self && self) ||
(typeof global == 'object' && global.global == global && global) ||
this || {};
var util = {
extend: function (target) {
for (var i = 1, len = arguments.length; i < len; i++) {
for (var prop in arguments[i]) {
if (arguments[i].hasOwnProperty(prop)) {
target[prop] = arguments[i][prop]
}
}
}
return target
},
isValidListener: function (listener) {
if (typeof listener === 'function') {
return true
} else if (listener && typeof listener === 'object') {
return util.isValidListener(listener.listener)
} else {
return false
}
},
addCSS: function (cssText) {
var style = document.createElement('style'), //创建一个style元素
head = document.head || document.getElementsByTagName('head')[0]; //获取head元素
style.type = 'text/css'; //这里必须显示设置style元素的type属性为text/css,否则在ie中不起作用
if (style.styleSheet) { //IE
var func = function () {
try { //防止IE中stylesheet数量超过限制而发生错误
style.styleSheet.cssText = cssText;
} catch (e) {
}
}
//如果当前styleSheet还不能用,则放到异步中则行
if (style.styleSheet.disabled) {
setTimeout(func, 10);
} else {
func();
}
} else { //w3c
//w3c浏览器中只要创建文本节点插入到style元素中就行了
var textNode = document.createTextNode(cssText);
style.appendChild(textNode);
}
head.appendChild(style); //把创建的style元素插入到head中
},
indexOf: function (array, item) {
if (array.indexOf) {
return array.indexOf(item);
} else {
var result = -1;
for (var i = 0, len = array.length; i < len; i++) {
if (array[i] === item) {
result = i;
break;
}
}
return result;
}
}
}
function EventEmitter() {
this._events = {}
}
EventEmitter.prototype.on = function (eventName, listener) {
if (!eventName || !listener) return;
if (!util.isValidListener(listener)) {
throw new TypeError('listener must be a function');
}
var events = this._events;
var listeners = events[eventName] = events[eventName] || [];
var listenerIsWrapped = typeof listener === 'object';
// 不重复添加事件
if (util.indexOf(listeners, listener) === -1) {
listeners.push(listenerIsWrapped ? listener : {
listener: listener,
once: false
});
}
return this;
};
EventEmitter.prototype.once = function (eventName, listener) {
return this.on(eventName, {
listener: listener,
once: true
})
};
EventEmitter.prototype.off = function (eventName, listener) {
var listeners = this._events[eventName];
if (!listeners) return;
var index;
for (var i = 0, len = listeners.length; i < len; i++) {
if (listeners[i] && listeners[i].listener === listener) {
index = i;
break;
}
}
if (typeof index !== 'undefined') {
listeners.splice(index, 1, null)
}
return this;
};
EventEmitter.prototype.emit = function (eventName, args) {
var listeners = this._events[eventName];
if (!listeners) return;
for (var i = 0; i < listeners.length; i++) {
var listener = listeners[i];
if (listener) {
listener.listener.apply(this, args || []);
if (listener.once) {
this.off(eventName, listener.listener)
}
}
}
return this;
};
// =================代码块2=========================================
function SliderTools(options) {
this.options = util.extend({}, this.constructor.defaultOptions, options)
this.init();
this.bindEvents();
this.diffX = 0;
this.flag = false;//是否拖动到最右侧
}
SliderTools.defaultOptions = {
el: document.body //默认放到body里
};
var proto = SliderTools.prototype = new EventEmitter();//SliderTools继承emitter
proto.constructor = SliderTools;//修正构造器
proto.init = function () {
this.createSlider();//创建插件所需要的dom元素
this.getElements();//获取创建好的元素
}
// =================代码块3=========================================
if (typeof exports != 'undefined' && !exports.nodeType) {
if (typeof module != 'undefined' && !module.nodeType && module.exports) {
exports = module.exports = SliderTools;
}
exports.SliderTools = SliderTools;
} else {
root.SliderTools = SliderTools;
}
}());
复制代码
代码块1是在判断是在浏览器环境还是nodeJS环境,方便代码三后期使用, 代码块2声明了一个对象SliderTools,将用户传进来的option和默认的defaultOption进行合并
编写核心函数1(创建dom和css)
proto.createSlider = function () {
this.options.el.innerHTML = '<div id="slider"><div class="drag_bg"></div><div class="drag_text" onselectstart="return false;" unselectable="on">拖动滑块验证</div><div class="handler handler_bg"></div></div>';//像指定元素中放置插件的dom元素
util.addCSS('ul,li {list-style: none;} a {text-decoration: none;} .wrap {width: 300px;height: 350px;text-align: center;margin: 150px auto;}.inner {padding: 15px;} .clearfix {overflow: hidden;_zoom: 1;} .none {display: none;} #slider {position:relative;background-color: #e8e8e8;width: 300px;height: 34px;line-height: 34px;text-align: center;} #slider .handler {position: absolute;top: 0px;left: 0px;width: 40px;height: 32px;border: 1px solid #ccc;cursor: move;} .handler_bg {background: #fff url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo0ZDhlNWY5My05NmI0LTRlNWQtOGFjYi03ZTY4OGYyMTU2ZTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTEyNTVEMURGMkVFMTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTEyNTVEMUNGMkVFMTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo2MTc5NzNmZS02OTQxLTQyOTYtYTIwNi02NDI2YTNkOWU5YmUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NGQ4ZTVmOTMtOTZiNC00ZTVkLThhY2ItN2U2ODhmMjE1NmU2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+YiRG4AAAALFJREFUeNpi/P//PwMlgImBQkA9A+bOnfsIiBOxKcInh+yCaCDuByoswaIOpxwjciACFegBqZ1AvBSIS5OTk/8TkmNEjwWgQiUgtQuIjwAxUF3yX3xyGIEIFLwHpKyAWB+I1xGSwxULIGf9A7mQkBwTlhBXAFLHgPgqEAcTkmNCU6AL9d8WII4HOvk3ITkWJAXWUMlOoGQHmsE45ViQ2KuBuASoYC4Wf+OUYxz6mQkgwAAN9mIrUReCXgAAAABJRU5ErkJggg==") no-repeat center;} .handler_ok_bg {background: #fff url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo0ZDhlNWY5My05NmI0LTRlNWQtOGFjYi03ZTY4OGYyMTU2ZTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDlBRDI3NjVGMkQ2MTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDlBRDI3NjRGMkQ2MTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDphNWEzMWNhMC1hYmViLTQxNWEtYTEwZS04Y2U5NzRlN2Q4YTEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NGQ4ZTVmOTMtOTZiNC00ZTVkLThhY2ItN2U2ODhmMjE1NmU2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+k+sHwwAAASZJREFUeNpi/P//PwMyKD8uZw+kUoDYEYgloMIvgHg/EM/ptHx0EFk9I8wAoEZ+IDUPiIMY8IN1QJwENOgj3ACo5gNAbMBAHLgAxA4gQ5igAnNJ0MwAVTsX7IKyY7L2UNuJAf+AmAmJ78AEDTBiwGYg5gbifCSxFCZoaBMCy4A4GOjnH0D6DpK4IxNSVIHAfSDOAeLraJrjgJp/AwPbHMhejiQnwYRmUzNQ4VQgDQqXK0ia/0I17wJiPmQNTNBEAgMlQIWiQA2vgWw7QppBekGxsAjIiEUSBNnsBDWEAY9mEFgMMgBk00E0iZtA7AHEctDQ58MRuA6wlLgGFMoMpIG1QFeGwAIxGZo8GUhIysmwQGSAZgwHaEZhICIzOaBkJkqyM0CAAQDGx279Jf50AAAAAABJRU5ErkJggg==") no-repeat center;}#slider .drag_bg {background-color: #7ac23c; height: 34px;width: 0px;} #slider .drag_text {position: absolute; top: 0px;width: 300px;-moz-user-select: none;-webkit-user-select: none;user-select: none;-o-user-select: none;-ms-user-select: none; }.unselect {-moz-user-select: none;-webkit-user-select: none; -ms-user-select: none;}.slide_ok {color: #fff;}')//像页面里add新的样式
}
proto.getElements = function () {
this.slider = document.querySelector('#slider');
this.drag_bg = document.querySelector('.drag_bg');
this.handler = document.querySelector('.handler');
}
复制代码
编写核心函数2(绑定事件)
proto.bindEvents = function () {
var self = this;
self.handler.onmousedown = function (e) {
self.diffX = e.clientX - self.handler.offsetLeft;
util.setClassName(self.slider, 'unselect'); //禁止选择样式
document.onmousemove = function (e) {
let deltaX = e.clientX - self.diffX;
if (deltaX >= self.slider.offsetWidth - self.handler.offsetWidth) { //拖动到了最右侧
deltaX = self.slider.offsetWidth - self.handler.offsetWidth;
self.flag = true;
} else if (deltaX <= 0) {
deltaX = 0;
self.flag = false;
} else {
self.flag = false;
}
util.setInlineStyle([self.handler], 'left', deltaX + 'px');
util.setInlineStyle([self.drag_bg], 'width', deltaX + 'px');
}
document.onmouseup = function (e) {
util.setClassName(self.slider, '')
if (self.flag) {
util.setClassName(self.slider, 'slide_ok') //拖动完成后的样式
util.addClass(self.handler, 'handler_ok_bg')////拖动完成后的样式
self.handler.onmousedown = null //防止拖动完成后再次拖动
self.emit('complete')//emit通知使用者的回调事件
} else {
util.setInlineStyle([self.handler], 'left', 0 + 'px');
util.setInlineStyle([self.drag_bg], 'width', 0 + 'px');
}
document.onmousemove = null;
document.onmouseup = null;
}
}
}
复制代码
添加工具方法(核心函数2中用到的)
var util = {
// ...初始框架里的那部分
setClassName(selector, className) {
selector.className = className;
},
addClass(selector, className) {
selector.classList.add(className);
},
setInlineStyle(selector, attr, content) {
let length = selector.length;
for (let i = 0; i < length; i++) {
selector[i].style[attr] = content;
}
},
}
复制代码
最终完整可运行代码
(function () {
var root = (typeof self == 'object' && self.self == self && self) ||
(typeof global == 'object' && global.global == global && global) ||
this || {};
var util = {
extend: function (target) {
for (var i = 1, len = arguments.length; i < len; i++) {
for (var prop in arguments[i]) {
if (arguments[i].hasOwnProperty(prop)) {
target[prop] = arguments[i][prop]
}
}
}
return target
},
setClassName(selector, className) {
selector.className = className;
},
addClass(selector, className) {
selector.classList.add(className);
},
setInlineStyle(selector, attr, content) {
let length = selector.length;
for (let i = 0; i < length; i++) {
selector[i].style[attr] = content;
}
},
isValidListener: function (listener) {
if (typeof listener === 'function') {
return true
} else if (listener && typeof listener === 'object') {
return util.isValidListener(listener.listener)
} else {
return false
}
},
addCSS: function (cssText) {
var style = document.createElement('style'), //创建一个style元素
head = document.head || document.getElementsByTagName('head')[0]; //获取head元素
style.type = 'text/css'; //这里必须显示设置style元素的type属性为text/css,否则在ie中不起作用
if (style.styleSheet) { //IE
var func = function () {
try { //防止IE中stylesheet数量超过限制而发生错误
style.styleSheet.cssText = cssText;
} catch (e) {
}
}
//如果当前styleSheet还不能用,则放到异步中则行
if (style.styleSheet.disabled) {
setTimeout(func, 10);
} else {
func();
}
} else { //w3c
//w3c浏览器中只要创建文本节点插入到style元素中就行了
var textNode = document.createTextNode(cssText);
style.appendChild(textNode);
}
head.appendChild(style); //把创建的style元素插入到head中
},
indexOf: function (array, item) {
if (array.indexOf) {
return array.indexOf(item);
} else {
var result = -1;
for (var i = 0, len = array.length; i < len; i++) {
if (array[i] === item) {
result = i;
break;
}
}
return result;
}
}
}
function EventEmitter() {
this._events = {}
}
EventEmitter.prototype.on = function (eventName, listener) {
if (!eventName || !listener) return;
if (!util.isValidListener(listener)) {
throw new TypeError('listener must be a function');
}
var events = this._events;
var listeners = events[eventName] = events[eventName] || [];
var listenerIsWrapped = typeof listener === 'object';
// 不重复添加事件
if (util.indexOf(listeners, listener) === -1) {
listeners.push(listenerIsWrapped ? listener : {
listener: listener,
once: false
});
}
return this;
};
EventEmitter.prototype.once = function (eventName, listener) {
return this.on(eventName, {
listener: listener,
once: true
})
};
EventEmitter.prototype.off = function (eventName, listener) {
var listeners = this._events[eventName];
if (!listeners) return;
var index;
for (var i = 0, len = listeners.length; i < len; i++) {
if (listeners[i] && listeners[i].listener === listener) {
index = i;
break;
}
}
if (typeof index !== 'undefined') {
listeners.splice(index, 1, null)
}
return this;
};
EventEmitter.prototype.emit = function (eventName, args) {
var listeners = this._events[eventName];
if (!listeners) return;
for (var i = 0; i < listeners.length; i++) {
var listener = listeners[i];
if (listener) {
listener.listener.apply(this, args || []);
if (listener.once) {
this.off(eventName, listener.listener)
}
}
}
return this;
};
function SliderTools(options) {
this.options = util.extend({}, this.constructor.defaultOptions, options)
this.init();
this.bindEvents();
this.diffX = 0;
this.flag = false;
}
SliderTools.VERSION = '1.0.0';
SliderTools.defaultOptions = {
el: document.body
};
var proto = SliderTools.prototype = new EventEmitter();
proto.constructor = SliderTools;
proto.init = function () {
this.createSlider();
this.getElements();
}
proto.createSlider = function () {
this.options.el.innerHTML = '<div id="slider"><div class="drag_bg"></div><div class="drag_text" onselectstart="return false;" unselectable="on">拖动滑块验证</div><div class="handler handler_bg"></div></div>';
util.addCSS('ul, li { list-style: none; } a { text-decoration: none; } .wrap { width: 300px; height: 350px; text-align: center; margin: 150px auto; } .inner { padding: 15px; } .clearfix { overflow: hidden; _zoom: 1; } .none { display: none; } #slider { position: relative; background-color: #e8e8e8; width: 300px; height: 34px; line-height: 34px; text-align: center; } #slider .handler { position: absolute; top: 0px; left: 0px; width: 40px; height: 32px; border: 1px solid #ccc; cursor: move;} .handler_bg { background: #fff url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo0ZDhlNWY5My05NmI0LTRlNWQtOGFjYi03ZTY4OGYyMTU2ZTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTEyNTVEMURGMkVFMTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTEyNTVEMUNGMkVFMTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo2MTc5NzNmZS02OTQxLTQyOTYtYTIwNi02NDI2YTNkOWU5YmUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NGQ4ZTVmOTMtOTZiNC00ZTVkLThhY2ItN2U2ODhmMjE1NmU2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+YiRG4AAAALFJREFUeNpi/P//PwMlgImBQkA9A+bOnfsIiBOxKcInh+yCaCDuByoswaIOpxwjciACFegBqZ1AvBSIS5OTk/8TkmNEjwWgQiUgtQuIjwAxUF3yX3xyGIEIFLwHpKyAWB+I1xGSwxULIGf9A7mQkBwTlhBXAFLHgPgqEAcTkmNCU6AL9d8WII4HOvk3ITkWJAXWUMlOoGQHmsE45ViQ2KuBuASoYC4Wf+OUYxz6mQkgwAAN9mIrUReCXgAAAABJRU5ErkJggg==") no-repeat center; } .handler_ok_bg { background: #fff url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo0ZDhlNWY5My05NmI0LTRlNWQtOGFjYi03ZTY4OGYyMTU2ZTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDlBRDI3NjVGMkQ2MTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDlBRDI3NjRGMkQ2MTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDphNWEzMWNhMC1hYmViLTQxNWEtYTEwZS04Y2U5NzRlN2Q4YTEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NGQ4ZTVmOTMtOTZiNC00ZTVkLThhY2ItN2U2ODhmMjE1NmU2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+k+sHwwAAASZJREFUeNpi/P//PwMyKD8uZw+kUoDYEYgloMIvgHg/EM/ptHx0EFk9I8wAoEZ+IDUPiIMY8IN1QJwENOgj3ACo5gNAbMBAHLgAxA4gQ5igAnNJ0MwAVTsX7IKyY7L2UNuJAf+AmAmJ78AEDTBiwGYg5gbifCSxFCZoaBMCy4A4GOjnH0D6DpK4IxNSVIHAfSDOAeLraJrjgJp/AwPbHMhejiQnwYRmUzNQ4VQgDQqXK0ia/0I17wJiPmQNTNBEAgMlQIWiQA2vgWw7QppBekGxsAjIiEUSBNnsBDWEAY9mEFgMMgBk00E0iZtA7AHEctDQ58MRuA6wlLgGFMoMpIG1QFeGwAIxGZo8GUhIysmwQGSAZgwHaEZhICIzOaBkJkqyM0CAAQDGx279Jf50AAAAAABJRU5ErkJggg==") no-repeat center; } #slider .drag_bg { background-color: #7ac23c; height: 34px; width: 0px; } #slider .drag_text { position: absolute; top: 0px; width: 300px; -moz-user-select: none; -webkit-user-select: none; user-select: none; -o-user-select: none; -ms-user-select: none; } .unselect { -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; } .slide_ok { color: #fff; }')
}
proto.getElements = function () {
this.slider = document.querySelector('#slider');
this.drag_bg = document.querySelector('.drag_bg');
this.handler = document.querySelector('.handler');
}
proto.bindEvents = function () {
var self = this;
self.handler.onmousedown = function (e) {
self.diffX = e.clientX - self.handler.offsetLeft;
util.setClassName(self.slider, 'unselect');
document.onmousemove = function (e) {
let deltaX = e.clientX - self.diffX;
if (deltaX >= self.slider.offsetWidth - self.handler.offsetWidth) {
deltaX = self.slider.offsetWidth - self.handler.offsetWidth;
self.flag = true;
} else if (deltaX <= 0) {
deltaX = 0;
self.flag = false;
} else {
self.flag = false;
}
util.setInlineStyle([self.handler], 'left', deltaX + 'px');
util.setInlineStyle([self.drag_bg], 'width', deltaX + 'px');
}
document.onmouseup = function (e) {
util.setClassName(self.slider, '')
if (self.flag) {
util.setClassName(self.slider, 'slide_ok')
util.addClass(self.handler, 'handler_ok_bg')
self.handler.onmousedown = null
self.emit('complete')
} else {
util.setInlineStyle([self.handler], 'left', 0 + 'px');
util.setInlineStyle([self.drag_bg], 'width', 0 + 'px');
}
document.onmousemove = null;
document.onmouseup = null;
}
}
}
if (typeof exports != 'undefined' && !exports.nodeType) {
if (typeof module != 'undefined' && !module.nodeType && module.exports) {
exports = module.exports = SliderTools;
}
exports.SliderTools = SliderTools;
} else {
root.SliderTools = SliderTools;
}
}());
let slider = new SliderTools();
slider.on('complete',() => {
alert('验证完成');
})
推荐JavaScript经典实例学习资料文章
《Pug 3.0.0正式发布,不再支持 Node.js 6/8》
《通过发布/订阅的设计模式搞懂 Node.js 核心模块 Events》
《「速围」Node.js V14.3.0 发布支持顶级 Await 和 REPL 增强功能》
《JavaScript 已进入第三个时代,未来将何去何从?》
《前端上传前预览文件 image、text、json、video、audio「实践」》
《深入细品 EventLoop 和浏览器渲染、帧动画、空闲回调的关系》
《推荐13个有用的JavaScript数组技巧「值得收藏」》
《36个工作中常用的JavaScript函数片段「值得收藏」》
《一文了解文件上传全过程(1.8w字深度解析)「前端进阶必备」》
《手把手教你如何编写一个前端图片压缩、方向纠正、预览、上传插件》
《JavaScript正则深入以及10个非常有意思的正则实战》
《前端开发规范:命名规范、html规范、css规范、js规范》
《100个原生JavaScript代码片段知识点详细汇总【实践】》
《手把手教你深入巩固JavaScript知识体系【思维导图】》
《一个合格的中级前端工程师需要掌握的 28 个 JavaScript 技巧》
《身份证号码的正则表达式及验证详解(JavaScript,Regex)》
《127个常用的JS代码片段,每段代码花30秒就能看懂-【上】》
《深入浅出讲解JS中this/apply/call/bind巧妙用法【实践】》
《干货满满!如何优雅简洁地实现时钟翻牌器(支持JS/Vue/React)》
《面试中教你绕过关于 JavaScript 作用域的 5 个坑》
作者:_release
转发链接:https://juejin.im/post/5ed37a73e51d45788c739784
相关推荐
- 你要如何学习写一个数据库内核(如何实现一个最简单的数据库)
-
数据库这个方向上还有许多细分方向,每个细分方向上都有许多知识。...
- 每个大数据架构师都需要的6个基本技能
-
为了成为一名出色的大数据架构师,首先必须成为一名数据架构师,但这两种角色的职责各有不同。数据分为结构化和非结构化两种。尽管大数据为各种规模的组织提供了许多洞察和分析的机会,但处理起来非常困难,并且需...
- 警惕!Spring Data MongoDB SpEL表达式注入漏洞风险通告
-
漏洞描述近日,亚信安全CERT监控到SpringDataMongoDB存在表达式注入漏洞(CVE-2022-22980),该漏洞源于SpringDataMongoDB应用程序在使用带有SpEL...
- 既然有MySQL了,为什么还要有MongoDB?
-
大家好,我是哪吒,最近项目在使用MongoDB作为图片和文档的存储数据库,为啥不直接存MySQL里,还要搭个MongoDB集群,麻不麻烦?...
- 分布式系统核心概念及实现(分布式核心原理解析)
-
一、分布式系统核心概念1.分布式系统的定义分布式系统是由多个独立的计算机(节点)通过网络连接,协同完成任务的系统。这些节点可以是物理机、虚拟机或容器。...
- nosql之mongodb(nosql数据库是国产的吗)
-
什么是MongoDB?MongoDB是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。...
- 如何治理非结构化数据?(非结构化化数据)
-
据调查,当前企业80%的数据为非结构化数据或半结构化数据,而结构化数据是他们管理的重点,非结构化数据却被忽视。然而,非结构化数据也有着它的价值。那么,如何治理非结构化数据?IDC调研显示,目前企业中8...
- Cloudera收购大数据加密初创企业Gazzang
-
Hadoop供应商Cloudera刚刚收购了专门研究下一代数据存储环境加密技术技术的初创企业Gazzang,但交易细节并未透露。这是Cloudera的第一笔重大收购。Gazzang成立于20...
- 全网最全95道MongoDB面试题1万字详细解析
-
1、mongodb是什么?MongoDB是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。在高负载的情况下,添加更多的节点,可以保证服务器性能。MongoDB旨在给WEB应...
- mongodb——视图(mongodb object)
-
MongoDB视图是一个可查询的对象,其内容由其他集合或视图上的聚合管道定义。MongoDB不会将视图内容持久化到磁盘。当客户端查询视图时,MongoDB可以要求客户端拥有查询视图的权限。MongoD...
- mongodb的优缺点及应用场景(mongodb 优点 应用场景)
-
一、MongoDB是什么1、维基百科MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。...
- 5款Syslog集中系统日志常用工具对比推荐
-
一、为何要集中管理Syslog?Syslog由Linux/Unix系统及其他网络设备生成,广泛分布于整个网络。因其包含关键信息,可用于识别网络中的恶意活动,所以必须对其进行持续监控。将Sys...
- 跨平台、多数据库支持的开源数据库管理工具——DBeaver
-
简介今天给大家推荐一个开源的数据库管理工具——DBeaver。它支持多种数据库系统,包括Mysql、Oracle、PostgreSQL、SLQLite、SQLServer等。DBeaver的界面友好...
- 强烈推荐!数据库管理工具:Navicat Premium 16.3.2 (64位)
-
NavicatPremium,一款集数据迁移、数据库管理、SQL/查询编辑、智能设计、高效协作于一体的全能数据库开发工具。无论你是MySQL、MariaDB、MongoDB、SQLServer、O...
- 3 年 Java 程序员还玩不转 MongoDB,网友:失望
-
一、什么场景使用MongoDB?...
你 发表评论:
欢迎- 一周热门
-
-
Linux:Ubuntu22.04上安装python3.11,简单易上手
-
宝马阿布达比分公司推出独特M4升级套件,整套升级约在20万
-
MATLAB中图片保存的五种方法(一)(matlab中保存图片命令)
-
别再傻傻搞不清楚Workstation Player和Workstation Pro的区别了
-
Linux上使用tinyproxy快速搭建HTTP/HTTPS代理器
-
如何提取、修改、强刷A卡bios a卡刷bios工具
-
Element Plus 的 Dialog 组件实现点击遮罩层不关闭对话框
-
日本组合“岚”将于2020年12月31日停止团体活动
-
SpringCloud OpenFeign 使用 okhttp 发送 HTTP 请求与 HTTP/2 探索
-
tinymce 号称富文本编辑器世界第一,大家同意么?
-
- 最近发表
- 标签列表
-
- dialog.js (57)
- importnew (44)
- windows93网页版 (44)
- yii2框架的优缺点 (45)
- tinyeditor (45)
- qt5.5 (60)
- windowsserver2016镜像下载 (52)
- okhttputils (51)
- android-gif-drawable (53)
- 时间轴插件 (56)
- docker systemd (65)
- slider.js (47)
- android webview缓存 (46)
- pagination.js (59)
- loadjs (62)
- openssl1.0.2 (48)
- velocity模板引擎 (48)
- pcre library (47)
- zabbix微信报警脚本 (63)
- jnetpcap (49)
- pdfrenderer (43)
- fastutil (48)
- uinavigationcontroller (53)
- bitbucket.org (44)
- python websocket-client (47)