New file |
| | |
| | | /** |
| | | @ Name:layui.cron Cron表达式解析器 |
| | | @ Author:贝哥哥 |
| | | @ License:MIT |
| | | */ |
| | | |
| | | layui.define(['lay', 'element', 'form'], function(exports){ //假如该组件依赖 layui.form |
| | | var $ = layui.$ |
| | | ,layer = layui.layer |
| | | ,lay = layui.lay |
| | | ,element = layui.element |
| | | ,form = layui.form |
| | | |
| | | |
| | | //字符常量 |
| | | ,MOD_NAME = 'cron', ELEM = '.layui-cron', THIS = 'layui-this', SHOW = 'layui-show', HIDE = 'layui-hide' |
| | | |
| | | ,ELEM_STATIC = 'layui-cron-static', ELEM_FOOTER = 'layui-cron-footer', ELEM_CONFIRM = '.cron-btns-confirm', ELEM_HINT = 'layui-cron-hint' |
| | | |
| | | ,ELEM_RUN_HINT = 'layui-cron-run-hint' |
| | | |
| | | //外部接口 |
| | | ,cron = { |
| | | v:'2.0.0' // cron 组件当前版本 |
| | | ,index: layui.cron ? (layui.cron.index + 10000) : 0 // corn 实例标识 |
| | | |
| | | //设置全局项 |
| | | ,set: function(options){ |
| | | var that = this; |
| | | that.config = $.extend({}, that.config, options); |
| | | return that; |
| | | } |
| | | |
| | | //事件监听 |
| | | ,on: function(events, callback){ |
| | | return layui.onevent.call(this, MOD_NAME, events, callback); |
| | | } |
| | | |
| | | //主体CSS等待事件 |
| | | ,ready: function (fn) { |
| | | var cssPath = layui.cache.base + "/cron.css?v=" + cron.v; |
| | | layui.link(cssPath, fn, "cron"); //此处的“cron”要对应 cron.css 中的样式: html #layuicss-cron{} |
| | | return this; |
| | | } |
| | | } |
| | | |
| | | //操作当前实例 |
| | | ,thisIns = function(){ |
| | | var that = this |
| | | ,options = that.config |
| | | ,id = options.id || options.index; |
| | | |
| | | return { |
| | | //提示框 |
| | | hint: function(content){ |
| | | that.hint.call(that, content); |
| | | } |
| | | ,config: options |
| | | } |
| | | } |
| | | |
| | | //构造器,创建实例 |
| | | ,Class = function(options){ |
| | | var that = this; |
| | | that.index = ++cron.index; |
| | | that.config = $.extend({}, that.config, cron.config, options); |
| | | cron.ready(function () { |
| | | that.init(); |
| | | }); |
| | | }; |
| | | |
| | | //默认配置 |
| | | Class.prototype.config = { |
| | | value: null // 当前表达式值,每秒执行一次 |
| | | ,isInitValue: true //用于控制是否自动向元素填充初始值(需配合 value 参数使用) |
| | | ,lang: "cn" //语言,只支持cn/en,即中文和英文 |
| | | ,tabs:[{key:'seconds',range:'0-59'},{key:'minutes',range:'0-59'},{key:'hours',range:'0-23'},{key:'days',range:'1-31'},{key:'months',range:'1-12'},{key:'weeks',range:'1-7'},{key:'years'}] |
| | | ,defaultCron: {seconds:"*",minutes:"*",hours:"*",days:"*", months:"*", weeks:"?", years:""} |
| | | ,trigger: "click" //呼出控件的事件 |
| | | ,btns: ['run', 'confirm'] //右下角显示的按钮,会按照数组顺序排列 |
| | | ,position: null //控件定位方式定位, 默认absolute,支持:fixed/absolute/static |
| | | ,zIndex: null //控件层叠顺序 |
| | | ,show: false //是否直接显示,如果设置 true,则默认直接显示控件 |
| | | ,showBottom: true //是否显示底部栏 |
| | | ,done: null //控件选择完毕后的回调,点击运行/确定也均会触发 |
| | | ,run: null // 最近运行时间接口 |
| | | }; |
| | | |
| | | //多语言 |
| | | Class.prototype.lang = function(){ |
| | | var that = this |
| | | ,options = that.config |
| | | ,text = { |
| | | cn: { |
| | | tabs: [{title: "秒"} |
| | | , {title: "分"} |
| | | , {title: "时"} |
| | | , {title: "日"} |
| | | , {title: "月"} |
| | | , {title: "周", rateBegin: "第", rateMid: "周的星期", rateEnd:""} |
| | | , {title: "年"}] |
| | | , every: "每" |
| | | , unspecified: "不指定" |
| | | , period: "周期" |
| | | , periodFrom: "从" |
| | | , rate: "按照" |
| | | , rateBegin: "从" |
| | | , rateMid: "开始,每" |
| | | , rateEnd: "执行一次" |
| | | , weekday: "工作日" |
| | | , weekdayPrefix: "每月" |
| | | , weekdaySuffix: "号最近的那个工作日" |
| | | , lastday: "本月最后一日" |
| | | , lastweek: "本月最后一个星期" |
| | | , custom: "指定" |
| | | ,tools: { |
| | | confirm: '确定' |
| | | ,run: '运行' |
| | | } |
| | | ,formatError: ['Cron格式不合法', '<br>已为你重置'] |
| | | } |
| | | ,en: { |
| | | tabs: [{title:"Seconds"} |
| | | , {title:"Minutes"} |
| | | , {title:"Hours"} |
| | | , {title:"Days"} |
| | | , {title:"Months"} |
| | | , {title:"Weeks"} |
| | | , {title:"Years"}] |
| | | , every:"Every " |
| | | , unspecified:"Unspecified" |
| | | , period:"Period" |
| | | , periodFrom: "From" |
| | | , rate: "According to" |
| | | , rateBegin: "begin at" |
| | | , rateMid: ", every" |
| | | , rateEnd: " execute once" |
| | | , weekday: "Weekday" |
| | | , weekdayPrefix: "Every month at " |
| | | , weekdaySuffix: "号最近的那个工作日" |
| | | , lastday: "Last day of the month" |
| | | , lastweek: "本月最后一个星期" |
| | | , custom: "Custom" |
| | | ,tools: { |
| | | confirm: 'Confirm' |
| | | ,run: 'Run' |
| | | } |
| | | ,formatError: ['The cron format error', '<br>It has been reset'] |
| | | } |
| | | }; |
| | | return text[options.lang] || text['cn']; |
| | | }; |
| | | |
| | | //初始准备 |
| | | Class.prototype.init = function(){ |
| | | var that = this |
| | | ,options = that.config |
| | | ,isStatic = options.position === 'static'; |
| | | |
| | | options.elem = lay(options.elem); |
| | | |
| | | options.eventElem = lay(options.eventElem); |
| | | |
| | | if(!options.elem[0]) return; |
| | | |
| | | //如果不是input|textarea元素,则默认采用click事件 |
| | | if(!that.isInput(options.elem[0])){ |
| | | if(options.trigger === 'focus'){ |
| | | options.trigger = 'click'; |
| | | } |
| | | } |
| | | |
| | | // 设置渲染所绑定元素的唯一KEY |
| | | if(!options.elem.attr('lay-key')){ |
| | | options.elem.attr('lay-key', that.index); |
| | | options.eventElem.attr('lay-key', that.index); |
| | | } |
| | | |
| | | // 当前实例主面板ID |
| | | that.elemID = 'layui-icon'+ options.elem.attr('lay-key'); |
| | | |
| | | //默认赋值 |
| | | if(options.value && options.isInitValue){ |
| | | that.setValue(options.value); |
| | | } |
| | | if(!options.value){ |
| | | options.value = options.elem[0].value||''; |
| | | } |
| | | var cronArr = options.value.split(' '); |
| | | if(cronArr.length >= 6){ |
| | | options.cron = { |
| | | seconds:cronArr[0], |
| | | minutes:cronArr[1], |
| | | hours:cronArr[2], |
| | | days:cronArr[3], |
| | | months:cronArr[4], |
| | | weeks:cronArr[5], |
| | | years:"", |
| | | }; |
| | | }else{ |
| | | options.cron = lay.extend({},options.defaultCron); |
| | | } |
| | | |
| | | |
| | | if(options.show || isStatic) that.render(); |
| | | isStatic || that.events(); |
| | | |
| | | |
| | | }; |
| | | |
| | | |
| | | // 控件主体渲染 |
| | | Class.prototype.render = function(){ |
| | | var that = this |
| | | ,options = that.config |
| | | ,lang = that.lang() |
| | | ,isStatic = options.position === 'static' |
| | | ,tabFilter = 'cron-tab' + options.elem.attr('lay-key') |
| | | //主面板 |
| | | ,elem = that.elem = lay.elem('div', { |
| | | id: that.elemID |
| | | ,'class': [ |
| | | 'layui-cron' |
| | | ,isStatic ? (' '+ ELEM_STATIC) : '' |
| | | ].join('') |
| | | }) |
| | | |
| | | // tab 内容区域 |
| | | ,elemTab = that.elemTab = lay.elem('div', { |
| | | 'class': 'layui-tab layui-tab-card', |
| | | 'lay-filter':tabFilter |
| | | }) |
| | | ,tabHead = lay.elem('ul',{ |
| | | 'class': 'layui-tab-title' |
| | | }) |
| | | ,tabContent = lay.elem('div',{ |
| | | 'class': 'layui-tab-content' |
| | | }) |
| | | |
| | | //底部区域 |
| | | ,divFooter = that.footer = lay.elem('div', { |
| | | 'class': ELEM_FOOTER |
| | | }); |
| | | |
| | | if(options.zIndex) elem.style.zIndex = options.zIndex; |
| | | |
| | | // 生成tab 内容区域 |
| | | elemTab.appendChild(tabHead); |
| | | elemTab.appendChild(tabContent); |
| | | lay.each(lang.tabs, function(i,item){ |
| | | // 表头 |
| | | var li = lay.elem('li',{ |
| | | 'class':i===0?THIS:"", |
| | | 'lay-id':i |
| | | }); |
| | | li.innerHTML = item.title; |
| | | tabHead.appendChild(li); |
| | | |
| | | // 表体 |
| | | tabContent.appendChild(that.getTabContentChildElem(i)); |
| | | }); |
| | | |
| | | // 主区域 |
| | | elemMain = that.elemMain = lay.elem('div', { |
| | | 'class': 'layui-cron-main' |
| | | }); |
| | | elemMain.appendChild(elemTab); |
| | | |
| | | //生成底部栏 |
| | | lay(divFooter).html(function(){ |
| | | var html = [], btns = []; |
| | | lay.each(options.btns, function(i, item){ |
| | | var title = lang.tools[item] || 'btn'; |
| | | btns.push('<span lay-type="'+ item +'" class="cron-btns-'+ item +'">'+ title +'</span>'); |
| | | }); |
| | | html.push('<div class="cron-footer-btns">'+ btns.join('') +'</div>'); |
| | | return html.join(''); |
| | | }()); |
| | | |
| | | //插入到主区域 |
| | | elem.appendChild(elemMain); |
| | | |
| | | options.showBottom && elem.appendChild(divFooter); |
| | | |
| | | |
| | | //移除上一个控件 |
| | | that.remove(Class.thisElemCron); |
| | | |
| | | //如果是静态定位,则插入到指定的容器中,否则,插入到body |
| | | isStatic ? options.elem.append(elem) : ( |
| | | document.body.appendChild(elem) |
| | | ,that.position() |
| | | ); |
| | | |
| | | |
| | | that.checkCron(); |
| | | |
| | | that.elemEvent(); // 主面板事件 |
| | | |
| | | Class.thisElemCron = that.elemID; |
| | | |
| | | form.render(); |
| | | |
| | | } |
| | | |
| | | // 渲染 tab 子控件 |
| | | Class.prototype.getTabContentChildElem = function(index){ |
| | | var that = this, |
| | | options = that.config, |
| | | tabItem = options.tabs[index], |
| | | tabItemKey = tabItem.key, |
| | | lang = that.lang(), |
| | | tabItemLang = lang.tabs[index], |
| | | cron = options.cron, |
| | | formFilter = 'cronForm'+tabItemKey+options.elem.attr('lay-key') |
| | | ,data = function(){ |
| | | if(cron[tabItemKey].indexOf('-') != -1){ |
| | | // 周期数据 |
| | | var arr = cron[tabItemKey].split('-'); |
| | | return { |
| | | type:'range', |
| | | start:arr[0], |
| | | end:arr[1] |
| | | }; |
| | | } |
| | | if(cron[tabItemKey].indexOf('/') != -1){ |
| | | // 频率数据 |
| | | var arr = cron[tabItemKey].split('/'); |
| | | return { |
| | | type:'rate', |
| | | begin:arr[0], |
| | | rate:arr[1] |
| | | }; |
| | | } |
| | | if(cron[tabItemKey].indexOf(',') != -1 || /^\+?[0-9][0-9]*$/.test(cron[tabItemKey])){ |
| | | // 按照指定执行 |
| | | var arr = cron[tabItemKey].split(',').map(Number); |
| | | return { |
| | | type:'custom', |
| | | values:arr |
| | | }; |
| | | } |
| | | if(cron[tabItemKey].indexOf('W') != -1){ |
| | | // 最近的工作日 |
| | | var value = cron[tabItemKey].replace('W',''); |
| | | return { |
| | | type:'weekday', |
| | | value: value |
| | | }; |
| | | } |
| | | if(index===3 && cron[tabItemKey] === 'L'){ |
| | | // 本月最后一日 |
| | | return { |
| | | type:'lastday', |
| | | value: 'L' |
| | | }; |
| | | } |
| | | if(index===5 && cron[tabItemKey].indexOf('L') != -1){ |
| | | // 本月最后一个周 value |
| | | var value = cron[tabItemKey].replace('L',''); |
| | | return { |
| | | type:'lastweek', |
| | | value: value |
| | | }; |
| | | } |
| | | if(cron[tabItemKey] === '*'){ |
| | | // 每次 |
| | | return { |
| | | type:'every', |
| | | value:'*' |
| | | }; |
| | | } |
| | | if(cron[tabItemKey] === '?'||cron[tabItemKey]===undefined||cron[tabItemKey]===''){ |
| | | // 不指定 |
| | | return { |
| | | type:'unspecified', |
| | | value:cron[tabItemKey] |
| | | }; |
| | | } |
| | | }() |
| | | , rangeData = function(){ |
| | | if(tabItem.range){ |
| | | var arr = tabItem.range.split('-'); |
| | | return { |
| | | min:parseInt(arr[0]), |
| | | max:parseInt(arr[1]) |
| | | }; |
| | | } |
| | | }(); |
| | | var elem = lay.elem('div', { |
| | | 'class': 'layui-tab-item layui-form '+(index===0?SHOW:"") |
| | | ,'lay-filter': formFilter |
| | | }); |
| | | |
| | | // 每次 |
| | | elem.appendChild(function(){ |
| | | var everyRadio = lay.elem('input',{ |
| | | 'name': tabItemKey+'[type]' |
| | | ,'type': 'radio' |
| | | ,'value': 'every' |
| | | ,'title': lang.every+tabItemLang.title |
| | | }); |
| | | if(data.type === 'every'){ |
| | | lay(everyRadio).attr('checked', true); |
| | | } |
| | | var everyDiv = lay.elem('div',{ |
| | | 'class':'cron-row' |
| | | }); |
| | | everyDiv.appendChild(everyRadio); |
| | | return everyDiv; |
| | | }()); |
| | | |
| | | // 不指定,从日开始 |
| | | if(index >= 3){ |
| | | elem.appendChild(function(){ |
| | | var unspecifiedRadio = lay.elem('input',{ |
| | | 'name': tabItemKey+'[type]' |
| | | ,'type': 'radio' |
| | | ,'value': 'unspecified' |
| | | ,'title': lang.unspecified |
| | | }); |
| | | if(data.type==='unspecified'){ |
| | | lay(unspecifiedRadio).attr('checked', true); |
| | | } |
| | | var unspecifiedDiv = lay.elem('div',{ |
| | | 'class':'cron-row' |
| | | }); |
| | | unspecifiedDiv.appendChild(unspecifiedRadio); |
| | | return unspecifiedDiv; |
| | | }()); |
| | | } |
| | | |
| | | // 周期 |
| | | var rangeChild = [function(){ |
| | | var rangeRadio = lay.elem('input',{ |
| | | 'name': tabItemKey+'[type]' |
| | | ,'type': 'radio' |
| | | ,'value': 'range' |
| | | ,'title': lang.period |
| | | }); |
| | | if(data.type === 'range'){ |
| | | lay(rangeRadio).attr('checked', true); |
| | | } |
| | | return rangeRadio; |
| | | }(),function(){ |
| | | var elem = lay.elem('div',{ |
| | | 'class':'cron-input-mid' |
| | | }); |
| | | elem.innerHTML = lang.periodFrom; |
| | | return elem; |
| | | }(),function(){ |
| | | var elem = lay.elem('input',{ |
| | | 'class':'cron-input', |
| | | 'type': 'number', |
| | | 'name': 'rangeStart', |
| | | 'value': data.start||'' |
| | | }); |
| | | return elem; |
| | | }(),function(){ |
| | | var elem = lay.elem('div',{ |
| | | 'class':'cron-input-mid' |
| | | }); |
| | | elem.innerHTML = '-'; |
| | | return elem; |
| | | }(),function(){ |
| | | var elem = lay.elem('input',{ |
| | | 'class':'cron-input', |
| | | 'type': 'number', |
| | | 'name': 'rangeEnd', |
| | | 'value': data.end||'' |
| | | }); |
| | | return elem; |
| | | }(),function(){ |
| | | var elem = lay.elem('div',{ |
| | | 'class':'cron-input-mid' |
| | | }); |
| | | elem.innerHTML = tabItemLang.title; |
| | | return elem; |
| | | }()] |
| | | |
| | | ,rangeDiv = lay.elem('div',{ |
| | | 'class':'cron-row' |
| | | }); |
| | | lay.each(rangeChild,function(i,item){ |
| | | rangeDiv.appendChild(item); |
| | | }); |
| | | if(tabItem.range){ |
| | | var rangeTip = lay.elem('div',{ |
| | | 'class':'cron-tips' |
| | | }); |
| | | rangeTip.innerHTML = ['(',tabItem.range,')'].join(''); |
| | | rangeDiv.appendChild(rangeTip); |
| | | } |
| | | elem.appendChild(rangeDiv); |
| | | |
| | | // 频率,年没有 |
| | | if(index<6){ |
| | | var rateChild = [function(){ |
| | | var rateRadio = lay.elem('input',{ |
| | | 'name': tabItemKey+'[type]' |
| | | ,'type': 'radio' |
| | | ,'value': 'rate' |
| | | ,'title': lang.rate |
| | | }); |
| | | if(data.type === 'rate'){ |
| | | lay(rateRadio).attr('checked', true); |
| | | } |
| | | return rateRadio; |
| | | }(),function(){ |
| | | var elem = lay.elem('div',{ |
| | | 'class':'cron-input-mid' |
| | | }); |
| | | elem.innerHTML = tabItemLang.rateBegin || lang.rateBegin; |
| | | return elem; |
| | | }(),function(){ |
| | | var elem = lay.elem('input',{ |
| | | 'class':'cron-input', |
| | | 'type': 'number', |
| | | 'name': 'begin', |
| | | 'value': data.begin||'' |
| | | }); |
| | | return elem; |
| | | }(),function(){ |
| | | var elem = lay.elem('div',{ |
| | | 'class':'cron-input-mid' |
| | | }); |
| | | elem.innerHTML = tabItemLang.rateMid || (tabItemLang.title+lang.rateMid); |
| | | return elem; |
| | | }(),function(){ |
| | | var elem = lay.elem('input',{ |
| | | 'class':'cron-input', |
| | | 'type': 'number', |
| | | 'name': 'rate', |
| | | 'value': data.rate||'' |
| | | }); |
| | | return elem; |
| | | }(),function(){ |
| | | var elem = lay.elem('div',{ |
| | | 'class':'cron-input-mid' |
| | | }); |
| | | elem.innerHTML = undefined!=tabItemLang.rateEnd ? tabItemLang.rateEnd:(tabItemLang.title+lang.rateEnd); |
| | | if(undefined!=tabItemLang.rateEnd&&tabItemLang.rateEnd===''){ |
| | | lay(elem).addClass(HIDE); |
| | | } |
| | | return elem; |
| | | }()] |
| | | |
| | | ,rateDiv = lay.elem('div',{ |
| | | 'class':'cron-row' |
| | | }); |
| | | lay.each(rateChild,function(i,item){ |
| | | rateDiv.appendChild(item); |
| | | }); |
| | | if(tabItem.range){ |
| | | var rateTip = lay.elem('div',{ |
| | | 'class':'cron-tips' |
| | | }); |
| | | if(index===5){ |
| | | // 周 |
| | | rateTip.innerHTML = '(1-4/1-7)'; |
| | | }else{ |
| | | rateTip.innerHTML = ['(',rangeData.min,'/',(rangeData.max+(index<=2?1:0)),')'].join(''); |
| | | } |
| | | rateDiv.appendChild(rateTip); |
| | | } |
| | | elem.appendChild(rateDiv); |
| | | } |
| | | |
| | | // 特殊:日(最近的工作日、最后一日),周(最后一周) |
| | | if(index===3){ |
| | | // 日 |
| | | // 最近的工作日 |
| | | var weekChild = [function(){ |
| | | var weekRadio = lay.elem('input',{ |
| | | 'name': tabItemKey+'[type]' |
| | | ,'type': 'radio' |
| | | ,'value': 'weekday' |
| | | ,'title': lang.weekday |
| | | }); |
| | | if(data.type === 'weekday'){ |
| | | lay(weekRadio).attr('checked', true); |
| | | } |
| | | return weekRadio; |
| | | }(),function(){ |
| | | var elem = lay.elem('div',{ |
| | | 'class':'cron-input-mid' |
| | | }); |
| | | elem.innerHTML = lang.weekdayPrefix; |
| | | return elem; |
| | | }(),function(){ |
| | | var elem = lay.elem('input',{ |
| | | 'class':'cron-input', |
| | | 'type': 'number', |
| | | 'name': 'weekday', |
| | | 'value': data.value||'' |
| | | }); |
| | | return elem; |
| | | }(),function(){ |
| | | var elem = lay.elem('div',{ |
| | | 'class':'cron-input-mid' |
| | | }); |
| | | elem.innerHTML = lang.weekdaySuffix; |
| | | return elem; |
| | | }(),function(){ |
| | | var elem = lay.elem('div',{ |
| | | 'class':'cron-tips' |
| | | }); |
| | | elem.innerHTML = ['(',tabItem.range,')'].join(''); |
| | | return elem; |
| | | }()] |
| | | |
| | | ,weekDiv = lay.elem('div',{ |
| | | 'class':'cron-row' |
| | | }); |
| | | lay.each(weekChild,function(i,item){ |
| | | weekDiv.appendChild(item); |
| | | }); |
| | | elem.appendChild(weekDiv); |
| | | |
| | | // 本月最后一日 |
| | | elem.appendChild(function(){ |
| | | var lastRadio = lay.elem('input',{ |
| | | 'name': tabItemKey+'[type]' |
| | | ,'type': 'radio' |
| | | ,'value': 'lastday' |
| | | ,'title': lang.lastday |
| | | }); |
| | | if(data.type === 'lastday'){ |
| | | lay(lastRadio).attr('checked', true); |
| | | } |
| | | var lastDiv = lay.elem('div',{ |
| | | 'class':'cron-row' |
| | | }); |
| | | lastDiv.appendChild(lastRadio); |
| | | return lastDiv; |
| | | }()); |
| | | |
| | | } |
| | | |
| | | if(index===5){ |
| | | // 本月最后一个周几 |
| | | var lastWeekChild = [function(){ |
| | | var lastWeekRadio = lay.elem('input',{ |
| | | 'name': tabItemKey+'[type]' |
| | | ,'type': 'radio' |
| | | ,'value': 'lastweek' |
| | | ,'title': lang.lastweek |
| | | }); |
| | | if(data.type === 'lastweek'){ |
| | | lay(lastWeekRadio).attr('checked', true); |
| | | } |
| | | return lastWeekRadio; |
| | | }(),function(){ |
| | | var elem = lay.elem('input',{ |
| | | 'class':'cron-input', |
| | | 'type': 'number', |
| | | 'name': 'lastweek', |
| | | 'value': data.value||'' |
| | | }); |
| | | return elem; |
| | | }(),function(){ |
| | | var elem = lay.elem('div',{ |
| | | 'class':'cron-tips' |
| | | }); |
| | | elem.innerHTML = ['(',tabItem.range,')'].join(''); |
| | | return elem; |
| | | }()] |
| | | |
| | | ,lastWeekDiv = lay.elem('div',{ |
| | | 'class':'cron-row' |
| | | }); |
| | | lay.each(lastWeekChild,function(i,item){ |
| | | lastWeekDiv.appendChild(item); |
| | | }); |
| | | elem.appendChild(lastWeekDiv); |
| | | |
| | | } |
| | | |
| | | // 指定 |
| | | if(index <= 5){ |
| | | elem.appendChild(function(){ |
| | | var customRadio = lay.elem('input',{ |
| | | 'name': tabItemKey+'[type]' |
| | | ,'type': 'radio' |
| | | ,'value': 'custom' |
| | | ,'title': lang.custom |
| | | }); |
| | | if(data.type === 'custom'){ |
| | | lay(customRadio).attr('checked', true); |
| | | } |
| | | var customDiv = lay.elem('div',{ |
| | | 'class':'cron-row' |
| | | }); |
| | | customDiv.appendChild(customRadio); |
| | | return customDiv; |
| | | }()); |
| | | |
| | | // 指定数值,时分秒显示两位数,自动补零 |
| | | elem.appendChild(function(){ |
| | | var customGrid = lay.elem('div',{ |
| | | 'class': 'cron-grid' |
| | | }); |
| | | var i = rangeData.min; |
| | | while(i<=rangeData.max){ |
| | | // 时分秒显示两位数,自动补零 |
| | | var gridItemValue = index<=2 ? lay.digit(i,2) : i; |
| | | var gridItem = lay.elem('input',{ |
| | | 'type': 'checkbox', |
| | | 'title': gridItemValue, |
| | | 'lay-skin': 'primary', |
| | | 'name':tabItemKey+'[custom]', |
| | | 'value':i |
| | | }); |
| | | if(data.values && data.values.includes(i)){ |
| | | lay(gridItem).attr('checked',true); |
| | | } |
| | | customGrid.appendChild(gridItem); |
| | | i++; |
| | | } |
| | | return customGrid; |
| | | }()); |
| | | } |
| | | |
| | | |
| | | return elem; |
| | | } |
| | | |
| | | //是否输入框 |
| | | Class.prototype.isInput = function(elem){ |
| | | return /input|textarea/.test(elem.tagName.toLocaleLowerCase()); |
| | | }; |
| | | |
| | | // 绑定的元素事件处理 |
| | | Class.prototype.events = function(){ |
| | | var that = this |
| | | ,options = that.config |
| | | |
| | | //绑定呼出控件事件 |
| | | ,showEvent = function(elem, bind){ |
| | | elem.on(options.trigger, function(){ |
| | | bind && (that.bindElem = this); |
| | | that.render(); |
| | | }); |
| | | }; |
| | | |
| | | if(!options.elem[0] || options.elem[0].eventHandler) return; |
| | | |
| | | showEvent(options.elem, 'bind'); |
| | | showEvent(options.eventElem); |
| | | |
| | | //绑定关闭控件事件 |
| | | lay(document).on('click', function(e){ |
| | | if(e.target === options.elem[0] |
| | | || e.target === options.eventElem[0] |
| | | || e.target === lay(options.closeStop)[0]){ |
| | | return; |
| | | } |
| | | that.remove(); |
| | | }).on('keydown', function(e){ |
| | | if(e.keyCode === 13){ |
| | | if(lay('#'+ that.elemID)[0] && that.elemID === Class.thisElemDate){ |
| | | e.preventDefault(); |
| | | lay(that.footer).find(ELEM_CONFIRM)[0].click(); |
| | | } |
| | | } |
| | | }); |
| | | |
| | | //自适应定位 |
| | | lay(window).on('resize', function(){ |
| | | if(!that.elem || !lay(ELEM)[0]){ |
| | | return false; |
| | | } |
| | | that.position(); |
| | | }); |
| | | |
| | | options.elem[0].eventHandler = true; |
| | | }; |
| | | |
| | | // 主面板事件 |
| | | Class.prototype.elemEvent = function(){ |
| | | var that = this |
| | | ,options = that.config |
| | | ,tabFilter = 'cron-tab' + options.elem.attr('lay-key'); |
| | | |
| | | // 阻止主面板点击冒泡,避免因触发文档事件而关闭主面 |
| | | lay(that.elem).on('click', function(e){ |
| | | lay.stope(e); |
| | | }); |
| | | |
| | | // tab选项卡切换 |
| | | var lis = lay(that.elemTab).find('li'); |
| | | lis.on('click',function(){ |
| | | var layid = lay(this).attr('lay-id'); |
| | | if(undefined === layid){ |
| | | return; |
| | | } |
| | | element.tabChange(tabFilter, layid); |
| | | }); |
| | | |
| | | // cron选项点击 |
| | | form.on('radio', function(data){ |
| | | var $parent = data.othis.parent(); |
| | | var formFilter = $parent.parent().attr('lay-filter'); |
| | | var formData = form.val(formFilter); |
| | | var radioType = data.value; |
| | | if('range'===radioType){ |
| | | // 范围 |
| | | form.val(formFilter,{ |
| | | rangeStart: formData.rangeStart||0, |
| | | rangeEnd: formData.rangeEnd||2 |
| | | }); |
| | | } |
| | | if('rate'===radioType){ |
| | | // 频率 |
| | | form.val(formFilter,{ |
| | | begin: formData.begin||0, |
| | | rate: formData.rate||2 |
| | | }); |
| | | } |
| | | if('custom'===radioType){ |
| | | // custom |
| | | var $grid = $parent.next(); |
| | | if($grid.find(':checkbox:checked').length<=0){ |
| | | $grid.children(':checkbox:first').next().click() |
| | | } |
| | | } |
| | | if('weekday'===radioType){ |
| | | // weekday |
| | | form.val(formFilter,{ |
| | | weekday: formData.weekday||1 |
| | | }); |
| | | } |
| | | if('lastweek'===radioType){ |
| | | // lastweek |
| | | form.val(formFilter,{ |
| | | lastweek: formData.lastweek||1 |
| | | }); |
| | | } |
| | | |
| | | }); |
| | | |
| | | //点击底部按钮 |
| | | lay(that.footer).find('span').on('click', function(){ |
| | | var type = lay(this).attr('lay-type'); |
| | | that.tool(this, type); |
| | | }); |
| | | }; |
| | | |
| | | //底部按钮点击事件 |
| | | Class.prototype.tool = function(btn, type){ |
| | | var that = this |
| | | ,options = that.config |
| | | ,lang = that.lang() |
| | | ,isStatic = options.position === 'static' |
| | | ,active = { |
| | | //运行 |
| | | run: function(){ |
| | | var value = that.parse(); |
| | | var loading = layer.load(); |
| | | $.get(options.run,{cron:value},function(res){ |
| | | layer.close(loading); |
| | | if(res.code !== 0){ |
| | | return that.hint(res.msg); |
| | | } |
| | | that.runHint(res.data); |
| | | },'json').fail(function(){ |
| | | layer.close(loading); |
| | | that.hint('服务器异常!'); |
| | | }); |
| | | } |
| | | |
| | | //确定 |
| | | ,confirm: function(){ |
| | | var value = that.parse(); |
| | | that.done([value]); |
| | | that.setValue(value).remove() |
| | | } |
| | | }; |
| | | active[type] && active[type](); |
| | | }; |
| | | |
| | | //执行 done/change 回调 |
| | | Class.prototype.done = function(param, type){ |
| | | var that = this |
| | | ,options = that.config; |
| | | |
| | | param = param || [that.parse()]; |
| | | typeof options[type || 'done'] === 'function' && options[type || 'done'].apply(options, param); |
| | | |
| | | return that; |
| | | }; |
| | | |
| | | // 解析cron表达式 |
| | | Class.prototype.parse = function(){ |
| | | var that = this |
| | | ,options = that.config |
| | | ,valueArr = []; |
| | | |
| | | lay.each(options.tabs, function(index, item){ |
| | | var key = item.key; |
| | | var formFilter = 'cronForm' + key + options.elem.attr('lay-key'); |
| | | var formData = form.val(formFilter); |
| | | var radioType = (key+'[type]'); |
| | | var current = ""; |
| | | if(formData[radioType] === 'every'){ |
| | | // 每次 |
| | | current = "*"; |
| | | } |
| | | if(formData[radioType] === 'range'){ |
| | | // 范围 |
| | | current = formData.rangeStart + "-" + formData.rangeEnd; |
| | | } |
| | | if(formData[radioType] === 'rate'){ |
| | | // 频率 |
| | | current = formData.begin + "/" + formData.rate; |
| | | } |
| | | if(formData[radioType] === 'custom'){ |
| | | // 指定 |
| | | var checkboxName = (item.key+'[custom]'); |
| | | var customArr = []; |
| | | $('input[name="' + checkboxName + '"]:checked').each(function() { |
| | | customArr.push($(this).val()); |
| | | }); |
| | | current = customArr.join(','); |
| | | } |
| | | if(formData[radioType] === 'weekday'){ |
| | | // 每月 formData.weekday 号最近的那个工作日 |
| | | current = formData.weekday + "W"; |
| | | } |
| | | if(formData[radioType] === 'lastday'){ |
| | | // 本月最后一日 |
| | | current = "L"; |
| | | } |
| | | if(formData[radioType] === 'lastweek'){ |
| | | // 本月最后星期 |
| | | current = formData.lastweek + "L"; |
| | | } |
| | | |
| | | if(formData[radioType] === 'unspecified' && index != 6){ |
| | | // 不指定 |
| | | current = "?"; |
| | | } |
| | | if(current !== ""){ |
| | | valueArr.push(current); |
| | | options.cron[key] = current; |
| | | } |
| | | }); |
| | | return valueArr.join(' '); |
| | | }; |
| | | |
| | | //控件移除 |
| | | Class.prototype.remove = function(prev){ |
| | | var that = this |
| | | ,options = that.config |
| | | ,elem = lay('#'+ (prev || that.elemID)); |
| | | if(!elem[0]) return that; |
| | | |
| | | if(!elem.hasClass(ELEM_STATIC)){ |
| | | that.checkCron(function(){ |
| | | elem.remove(); |
| | | }); |
| | | } |
| | | return that; |
| | | }; |
| | | |
| | | //定位算法 |
| | | Class.prototype.position = function(){ |
| | | var that = this |
| | | ,options = that.config; |
| | | lay.position(that.bindElem || options.elem[0], that.elem, { |
| | | position: options.position |
| | | }); |
| | | return that; |
| | | }; |
| | | |
| | | //提示 |
| | | Class.prototype.hint = function(content){ |
| | | var that = this |
| | | ,options = that.config |
| | | ,div = lay.elem('div', { |
| | | 'class': ELEM_HINT |
| | | }); |
| | | |
| | | if(!that.elem) return; |
| | | |
| | | div.innerHTML = content || ''; |
| | | lay(that.elem).find('.'+ ELEM_HINT).remove(); |
| | | that.elem.appendChild(div); |
| | | |
| | | clearTimeout(that.hinTimer); |
| | | that.hinTimer = setTimeout(function(){ |
| | | lay(that.elem).find('.'+ ELEM_HINT).remove(); |
| | | }, 3000); |
| | | }; |
| | | |
| | | //运行提示 |
| | | Class.prototype.runHint = function(runList){ |
| | | var that = this |
| | | ,options = that.config |
| | | ,div = lay.elem('div', { |
| | | 'class': ELEM_RUN_HINT |
| | | }); |
| | | // debugger; |
| | | if(!that.elem||!runList||!runList.length) return; |
| | | |
| | | |
| | | lay(div).html(function(){ |
| | | var html = []; |
| | | lay.each(runList, function(i, item){ |
| | | html.push('<div class="cron-run-list">'+ item +'</div>'); |
| | | }); |
| | | return html.join(''); |
| | | }()); |
| | | |
| | | lay(that.elem).find('.'+ ELEM_RUN_HINT).remove(); |
| | | that.elem.appendChild(div); |
| | | }; |
| | | |
| | | //赋值 |
| | | Class.prototype.setValue = function(value=''){ |
| | | var that = this |
| | | ,options = that.config |
| | | ,elem = that.bindElem || options.elem[0] |
| | | ,valType = that.isInput(elem) ? 'val' : 'html' |
| | | |
| | | options.position === 'static' || lay(elem)[valType](value || ''); |
| | | elem.textContent = '生成'; |
| | | return this; |
| | | }; |
| | | |
| | | //cron校验 |
| | | Class.prototype.checkCron = function(fn){ |
| | | var that = this |
| | | ,options = that.config |
| | | ,lang = that.lang() |
| | | ,elem = that.bindElem || options.elem[0] |
| | | ,value = that.isInput(elem) ? elem.value : (options.position === 'static' ? '' : elem.innerHTML) |
| | | |
| | | ,checkValid = function(value=""){ |
| | | |
| | | }; |
| | | |
| | | // cron 值,多个空格替换为一个空格,去掉首尾空格 |
| | | value = value || options.value; |
| | | if(typeof value === 'string'){ |
| | | value = value.replace(/\s+/g, ' ').replace(/^\s|\s$/g, ''); |
| | | } |
| | | |
| | | if(fn==='init') return checkValid(value),that; |
| | | |
| | | value = that.parse(); |
| | | if(value){ |
| | | that.setValue(value); |
| | | } |
| | | fn && fn(); |
| | | return that; |
| | | }; |
| | | |
| | | //核心入口 |
| | | cron.render = function(options){ |
| | | var ins = new Class(options); |
| | | return thisIns.call(ins); |
| | | }; |
| | | |
| | | exports('cron', cron); |
| | | }); |
New file |
| | |
| | | /**! |
| | | * Sortable 1.10.2 |
| | | * @author RubaXa <trash@rubaxa.org> |
| | | * @author owenm <owen23355@gmail.com> |
| | | * @license MIT |
| | | */ |
| | | (function (global, factory) { |
| | | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : |
| | | typeof define === 'function' && define.amd ? define(factory) : |
| | | (global = global || self, global.Sortable = factory()); |
| | | }(this, function () { 'use strict'; |
| | | |
| | | function _typeof(obj) { |
| | | if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { |
| | | _typeof = function (obj) { |
| | | return typeof obj; |
| | | }; |
| | | } else { |
| | | _typeof = function (obj) { |
| | | return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; |
| | | }; |
| | | } |
| | | |
| | | return _typeof(obj); |
| | | } |
| | | |
| | | function _defineProperty(obj, key, value) { |
| | | if (key in obj) { |
| | | Object.defineProperty(obj, key, { |
| | | value: value, |
| | | enumerable: true, |
| | | configurable: true, |
| | | writable: true |
| | | }); |
| | | } else { |
| | | obj[key] = value; |
| | | } |
| | | |
| | | return obj; |
| | | } |
| | | |
| | | function _extends() { |
| | | _extends = Object.assign || function (target) { |
| | | for (var i = 1; i < arguments.length; i++) { |
| | | var source = arguments[i]; |
| | | |
| | | for (var key in source) { |
| | | if (Object.prototype.hasOwnProperty.call(source, key)) { |
| | | target[key] = source[key]; |
| | | } |
| | | } |
| | | } |
| | | |
| | | return target; |
| | | }; |
| | | |
| | | return _extends.apply(this, arguments); |
| | | } |
| | | |
| | | function _objectSpread(target) { |
| | | for (var i = 1; i < arguments.length; i++) { |
| | | var source = arguments[i] != null ? arguments[i] : {}; |
| | | var ownKeys = Object.keys(source); |
| | | |
| | | if (typeof Object.getOwnPropertySymbols === 'function') { |
| | | ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { |
| | | return Object.getOwnPropertyDescriptor(source, sym).enumerable; |
| | | })); |
| | | } |
| | | |
| | | ownKeys.forEach(function (key) { |
| | | _defineProperty(target, key, source[key]); |
| | | }); |
| | | } |
| | | |
| | | return target; |
| | | } |
| | | |
| | | function _objectWithoutPropertiesLoose(source, excluded) { |
| | | if (source == null) return {}; |
| | | var target = {}; |
| | | var sourceKeys = Object.keys(source); |
| | | var key, i; |
| | | |
| | | for (i = 0; i < sourceKeys.length; i++) { |
| | | key = sourceKeys[i]; |
| | | if (excluded.indexOf(key) >= 0) continue; |
| | | target[key] = source[key]; |
| | | } |
| | | |
| | | return target; |
| | | } |
| | | |
| | | function _objectWithoutProperties(source, excluded) { |
| | | if (source == null) return {}; |
| | | |
| | | var target = _objectWithoutPropertiesLoose(source, excluded); |
| | | |
| | | var key, i; |
| | | |
| | | if (Object.getOwnPropertySymbols) { |
| | | var sourceSymbolKeys = Object.getOwnPropertySymbols(source); |
| | | |
| | | for (i = 0; i < sourceSymbolKeys.length; i++) { |
| | | key = sourceSymbolKeys[i]; |
| | | if (excluded.indexOf(key) >= 0) continue; |
| | | if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; |
| | | target[key] = source[key]; |
| | | } |
| | | } |
| | | |
| | | return target; |
| | | } |
| | | |
| | | function _toConsumableArray(arr) { |
| | | return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); |
| | | } |
| | | |
| | | function _arrayWithoutHoles(arr) { |
| | | if (Array.isArray(arr)) { |
| | | for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; |
| | | |
| | | return arr2; |
| | | } |
| | | } |
| | | |
| | | function _iterableToArray(iter) { |
| | | if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); |
| | | } |
| | | |
| | | function _nonIterableSpread() { |
| | | throw new TypeError("Invalid attempt to spread non-iterable instance"); |
| | | } |
| | | |
| | | var version = "1.10.2"; |
| | | |
| | | function userAgent(pattern) { |
| | | if (typeof window !== 'undefined' && window.navigator) { |
| | | return !! |
| | | /*@__PURE__*/ |
| | | navigator.userAgent.match(pattern); |
| | | } |
| | | } |
| | | |
| | | var IE11OrLess = userAgent(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i); |
| | | var Edge = userAgent(/Edge/i); |
| | | var FireFox = userAgent(/firefox/i); |
| | | var Safari = userAgent(/safari/i) && !userAgent(/chrome/i) && !userAgent(/android/i); |
| | | var IOS = userAgent(/iP(ad|od|hone)/i); |
| | | var ChromeForAndroid = userAgent(/chrome/i) && userAgent(/android/i); |
| | | |
| | | var captureMode = { |
| | | capture: false, |
| | | passive: false |
| | | }; |
| | | |
| | | function on(el, event, fn) { |
| | | el.addEventListener(event, fn, !IE11OrLess && captureMode); |
| | | } |
| | | |
| | | function off(el, event, fn) { |
| | | el.removeEventListener(event, fn, !IE11OrLess && captureMode); |
| | | } |
| | | |
| | | function matches( |
| | | /**HTMLElement*/ |
| | | el, |
| | | /**String*/ |
| | | selector) { |
| | | if (!selector) return; |
| | | selector[0] === '>' && (selector = selector.substring(1)); |
| | | |
| | | if (el) { |
| | | try { |
| | | if (el.matches) { |
| | | return el.matches(selector); |
| | | } else if (el.msMatchesSelector) { |
| | | return el.msMatchesSelector(selector); |
| | | } else if (el.webkitMatchesSelector) { |
| | | return el.webkitMatchesSelector(selector); |
| | | } |
| | | } catch (_) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | |
| | | function getParentOrHost(el) { |
| | | return el.host && el !== document && el.host.nodeType ? el.host : el.parentNode; |
| | | } |
| | | |
| | | function closest( |
| | | /**HTMLElement*/ |
| | | el, |
| | | /**String*/ |
| | | selector, |
| | | /**HTMLElement*/ |
| | | ctx, includeCTX) { |
| | | if (el) { |
| | | ctx = ctx || document; |
| | | |
| | | do { |
| | | if (selector != null && (selector[0] === '>' ? el.parentNode === ctx && matches(el, selector) : matches(el, selector)) || includeCTX && el === ctx) { |
| | | return el; |
| | | } |
| | | |
| | | if (el === ctx) break; |
| | | /* jshint boss:true */ |
| | | } while (el = getParentOrHost(el)); |
| | | } |
| | | |
| | | return null; |
| | | } |
| | | |
| | | var R_SPACE = /\s+/g; |
| | | |
| | | function toggleClass(el, name, state) { |
| | | if (el && name) { |
| | | if (el.classList) { |
| | | el.classList[state ? 'add' : 'remove'](name); |
| | | } else { |
| | | var className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' '); |
| | | el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' '); |
| | | } |
| | | } |
| | | } |
| | | |
| | | function css(el, prop, val) { |
| | | var style = el && el.style; |
| | | |
| | | if (style) { |
| | | if (val === void 0) { |
| | | if (document.defaultView && document.defaultView.getComputedStyle) { |
| | | val = document.defaultView.getComputedStyle(el, ''); |
| | | } else if (el.currentStyle) { |
| | | val = el.currentStyle; |
| | | } |
| | | |
| | | return prop === void 0 ? val : val[prop]; |
| | | } else { |
| | | if (!(prop in style) && prop.indexOf('webkit') === -1) { |
| | | prop = '-webkit-' + prop; |
| | | } |
| | | |
| | | style[prop] = val + (typeof val === 'string' ? '' : 'px'); |
| | | } |
| | | } |
| | | } |
| | | |
| | | function matrix(el, selfOnly) { |
| | | var appliedTransforms = ''; |
| | | |
| | | if (typeof el === 'string') { |
| | | appliedTransforms = el; |
| | | } else { |
| | | do { |
| | | var transform = css(el, 'transform'); |
| | | |
| | | if (transform && transform !== 'none') { |
| | | appliedTransforms = transform + ' ' + appliedTransforms; |
| | | } |
| | | /* jshint boss:true */ |
| | | |
| | | } while (!selfOnly && (el = el.parentNode)); |
| | | } |
| | | |
| | | var matrixFn = window.DOMMatrix || window.WebKitCSSMatrix || window.CSSMatrix || window.MSCSSMatrix; |
| | | /*jshint -W056 */ |
| | | |
| | | return matrixFn && new matrixFn(appliedTransforms); |
| | | } |
| | | |
| | | function find(ctx, tagName, iterator) { |
| | | if (ctx) { |
| | | var list = ctx.getElementsByTagName(tagName), |
| | | i = 0, |
| | | n = list.length; |
| | | |
| | | if (iterator) { |
| | | for (; i < n; i++) { |
| | | iterator(list[i], i); |
| | | } |
| | | } |
| | | |
| | | return list; |
| | | } |
| | | |
| | | return []; |
| | | } |
| | | |
| | | function getWindowScrollingElement() { |
| | | var scrollingElement = document.scrollingElement; |
| | | |
| | | if (scrollingElement) { |
| | | return scrollingElement; |
| | | } else { |
| | | return document.documentElement; |
| | | } |
| | | } |
| | | /** |
| | | * Returns the "bounding client rect" of given element |
| | | * @param {HTMLElement} el The element whose boundingClientRect is wanted |
| | | * @param {[Boolean]} relativeToContainingBlock Whether the rect should be relative to the containing block of (including) the container |
| | | * @param {[Boolean]} relativeToNonStaticParent Whether the rect should be relative to the relative parent of (including) the contaienr |
| | | * @param {[Boolean]} undoScale Whether the container's scale() should be undone |
| | | * @param {[HTMLElement]} container The parent the element will be placed in |
| | | * @return {Object} The boundingClientRect of el, with specified adjustments |
| | | */ |
| | | |
| | | |
| | | function getRect(el, relativeToContainingBlock, relativeToNonStaticParent, undoScale, container) { |
| | | if (!el.getBoundingClientRect && el !== window) return; |
| | | var elRect, top, left, bottom, right, height, width; |
| | | |
| | | if (el !== window && el !== getWindowScrollingElement()) { |
| | | elRect = el.getBoundingClientRect(); |
| | | top = elRect.top; |
| | | left = elRect.left; |
| | | bottom = elRect.bottom; |
| | | right = elRect.right; |
| | | height = elRect.height; |
| | | width = elRect.width; |
| | | } else { |
| | | top = 0; |
| | | left = 0; |
| | | bottom = window.innerHeight; |
| | | right = window.innerWidth; |
| | | height = window.innerHeight; |
| | | width = window.innerWidth; |
| | | } |
| | | |
| | | if ((relativeToContainingBlock || relativeToNonStaticParent) && el !== window) { |
| | | // Adjust for translate() |
| | | container = container || el.parentNode; // solves #1123 (see: https://stackoverflow.com/a/37953806/6088312) |
| | | // Not needed on <= IE11 |
| | | |
| | | if (!IE11OrLess) { |
| | | do { |
| | | if (container && container.getBoundingClientRect && (css(container, 'transform') !== 'none' || relativeToNonStaticParent && css(container, 'position') !== 'static')) { |
| | | var containerRect = container.getBoundingClientRect(); // Set relative to edges of padding box of container |
| | | |
| | | top -= containerRect.top + parseInt(css(container, 'border-top-width')); |
| | | left -= containerRect.left + parseInt(css(container, 'border-left-width')); |
| | | bottom = top + elRect.height; |
| | | right = left + elRect.width; |
| | | break; |
| | | } |
| | | /* jshint boss:true */ |
| | | |
| | | } while (container = container.parentNode); |
| | | } |
| | | } |
| | | |
| | | if (undoScale && el !== window) { |
| | | // Adjust for scale() |
| | | var elMatrix = matrix(container || el), |
| | | scaleX = elMatrix && elMatrix.a, |
| | | scaleY = elMatrix && elMatrix.d; |
| | | |
| | | if (elMatrix) { |
| | | top /= scaleY; |
| | | left /= scaleX; |
| | | width /= scaleX; |
| | | height /= scaleY; |
| | | bottom = top + height; |
| | | right = left + width; |
| | | } |
| | | } |
| | | |
| | | return { |
| | | top: top, |
| | | left: left, |
| | | bottom: bottom, |
| | | right: right, |
| | | width: width, |
| | | height: height |
| | | }; |
| | | } |
| | | /** |
| | | * Checks if a side of an element is scrolled past a side of its parents |
| | | * @param {HTMLElement} el The element who's side being scrolled out of view is in question |
| | | * @param {String} elSide Side of the element in question ('top', 'left', 'right', 'bottom') |
| | | * @param {String} parentSide Side of the parent in question ('top', 'left', 'right', 'bottom') |
| | | * @return {HTMLElement} The parent scroll element that the el's side is scrolled past, or null if there is no such element |
| | | */ |
| | | |
| | | |
| | | function isScrolledPast(el, elSide, parentSide) { |
| | | var parent = getParentAutoScrollElement(el, true), |
| | | elSideVal = getRect(el)[elSide]; |
| | | /* jshint boss:true */ |
| | | |
| | | while (parent) { |
| | | var parentSideVal = getRect(parent)[parentSide], |
| | | visible = void 0; |
| | | |
| | | if (parentSide === 'top' || parentSide === 'left') { |
| | | visible = elSideVal >= parentSideVal; |
| | | } else { |
| | | visible = elSideVal <= parentSideVal; |
| | | } |
| | | |
| | | if (!visible) return parent; |
| | | if (parent === getWindowScrollingElement()) break; |
| | | parent = getParentAutoScrollElement(parent, false); |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | /** |
| | | * Gets nth child of el, ignoring hidden children, sortable's elements (does not ignore clone if it's visible) |
| | | * and non-draggable elements |
| | | * @param {HTMLElement} el The parent element |
| | | * @param {Number} childNum The index of the child |
| | | * @param {Object} options Parent Sortable's options |
| | | * @return {HTMLElement} The child at index childNum, or null if not found |
| | | */ |
| | | |
| | | |
| | | function getChild(el, childNum, options) { |
| | | var currentChild = 0, |
| | | i = 0, |
| | | children = el.children; |
| | | |
| | | while (i < children.length) { |
| | | if (children[i].style.display !== 'none' && children[i] !== Sortable.ghost && children[i] !== Sortable.dragged && closest(children[i], options.draggable, el, false)) { |
| | | if (currentChild === childNum) { |
| | | return children[i]; |
| | | } |
| | | |
| | | currentChild++; |
| | | } |
| | | |
| | | i++; |
| | | } |
| | | |
| | | return null; |
| | | } |
| | | /** |
| | | * Gets the last child in the el, ignoring ghostEl or invisible elements (clones) |
| | | * @param {HTMLElement} el Parent element |
| | | * @param {selector} selector Any other elements that should be ignored |
| | | * @return {HTMLElement} The last child, ignoring ghostEl |
| | | */ |
| | | |
| | | |
| | | function lastChild(el, selector) { |
| | | var last = el.lastElementChild; |
| | | |
| | | while (last && (last === Sortable.ghost || css(last, 'display') === 'none' || selector && !matches(last, selector))) { |
| | | last = last.previousElementSibling; |
| | | } |
| | | |
| | | return last || null; |
| | | } |
| | | /** |
| | | * Returns the index of an element within its parent for a selected set of |
| | | * elements |
| | | * @param {HTMLElement} el |
| | | * @param {selector} selector |
| | | * @return {number} |
| | | */ |
| | | |
| | | |
| | | function index(el, selector) { |
| | | var index = 0; |
| | | |
| | | if (!el || !el.parentNode) { |
| | | return -1; |
| | | } |
| | | /* jshint boss:true */ |
| | | |
| | | |
| | | while (el = el.previousElementSibling) { |
| | | if (el.nodeName.toUpperCase() !== 'TEMPLATE' && el !== Sortable.clone && (!selector || matches(el, selector))) { |
| | | index++; |
| | | } |
| | | } |
| | | |
| | | return index; |
| | | } |
| | | /** |
| | | * Returns the scroll offset of the given element, added with all the scroll offsets of parent elements. |
| | | * The value is returned in real pixels. |
| | | * @param {HTMLElement} el |
| | | * @return {Array} Offsets in the format of [left, top] |
| | | */ |
| | | |
| | | |
| | | function getRelativeScrollOffset(el) { |
| | | var offsetLeft = 0, |
| | | offsetTop = 0, |
| | | winScroller = getWindowScrollingElement(); |
| | | |
| | | if (el) { |
| | | do { |
| | | var elMatrix = matrix(el), |
| | | scaleX = elMatrix.a, |
| | | scaleY = elMatrix.d; |
| | | offsetLeft += el.scrollLeft * scaleX; |
| | | offsetTop += el.scrollTop * scaleY; |
| | | } while (el !== winScroller && (el = el.parentNode)); |
| | | } |
| | | |
| | | return [offsetLeft, offsetTop]; |
| | | } |
| | | /** |
| | | * Returns the index of the object within the given array |
| | | * @param {Array} arr Array that may or may not hold the object |
| | | * @param {Object} obj An object that has a key-value pair unique to and identical to a key-value pair in the object you want to find |
| | | * @return {Number} The index of the object in the array, or -1 |
| | | */ |
| | | |
| | | |
| | | function indexOfObject(arr, obj) { |
| | | for (var i in arr) { |
| | | if (!arr.hasOwnProperty(i)) continue; |
| | | |
| | | for (var key in obj) { |
| | | if (obj.hasOwnProperty(key) && obj[key] === arr[i][key]) return Number(i); |
| | | } |
| | | } |
| | | |
| | | return -1; |
| | | } |
| | | |
| | | function getParentAutoScrollElement(el, includeSelf) { |
| | | // skip to window |
| | | if (!el || !el.getBoundingClientRect) return getWindowScrollingElement(); |
| | | var elem = el; |
| | | var gotSelf = false; |
| | | |
| | | do { |
| | | // we don't need to get elem css if it isn't even overflowing in the first place (performance) |
| | | if (elem.clientWidth < elem.scrollWidth || elem.clientHeight < elem.scrollHeight) { |
| | | var elemCSS = css(elem); |
| | | |
| | | if (elem.clientWidth < elem.scrollWidth && (elemCSS.overflowX == 'auto' || elemCSS.overflowX == 'scroll') || elem.clientHeight < elem.scrollHeight && (elemCSS.overflowY == 'auto' || elemCSS.overflowY == 'scroll')) { |
| | | if (!elem.getBoundingClientRect || elem === document.body) return getWindowScrollingElement(); |
| | | if (gotSelf || includeSelf) return elem; |
| | | gotSelf = true; |
| | | } |
| | | } |
| | | /* jshint boss:true */ |
| | | |
| | | } while (elem = elem.parentNode); |
| | | |
| | | return getWindowScrollingElement(); |
| | | } |
| | | |
| | | function extend(dst, src) { |
| | | if (dst && src) { |
| | | for (var key in src) { |
| | | if (src.hasOwnProperty(key)) { |
| | | dst[key] = src[key]; |
| | | } |
| | | } |
| | | } |
| | | |
| | | return dst; |
| | | } |
| | | |
| | | function isRectEqual(rect1, rect2) { |
| | | return Math.round(rect1.top) === Math.round(rect2.top) && Math.round(rect1.left) === Math.round(rect2.left) && Math.round(rect1.height) === Math.round(rect2.height) && Math.round(rect1.width) === Math.round(rect2.width); |
| | | } |
| | | |
| | | var _throttleTimeout; |
| | | |
| | | function throttle(callback, ms) { |
| | | return function () { |
| | | if (!_throttleTimeout) { |
| | | var args = arguments, |
| | | _this = this; |
| | | |
| | | if (args.length === 1) { |
| | | callback.call(_this, args[0]); |
| | | } else { |
| | | callback.apply(_this, args); |
| | | } |
| | | |
| | | _throttleTimeout = setTimeout(function () { |
| | | _throttleTimeout = void 0; |
| | | }, ms); |
| | | } |
| | | }; |
| | | } |
| | | |
| | | function cancelThrottle() { |
| | | clearTimeout(_throttleTimeout); |
| | | _throttleTimeout = void 0; |
| | | } |
| | | |
| | | function scrollBy(el, x, y) { |
| | | el.scrollLeft += x; |
| | | el.scrollTop += y; |
| | | } |
| | | |
| | | function clone(el) { |
| | | var Polymer = window.Polymer; |
| | | var $ = window.jQuery || window.Zepto; |
| | | |
| | | if (Polymer && Polymer.dom) { |
| | | return Polymer.dom(el).cloneNode(true); |
| | | } else if ($) { |
| | | return $(el).clone(true)[0]; |
| | | } else { |
| | | return el.cloneNode(true); |
| | | } |
| | | } |
| | | |
| | | function setRect(el, rect) { |
| | | css(el, 'position', 'absolute'); |
| | | css(el, 'top', rect.top); |
| | | css(el, 'left', rect.left); |
| | | css(el, 'width', rect.width); |
| | | css(el, 'height', rect.height); |
| | | } |
| | | |
| | | function unsetRect(el) { |
| | | css(el, 'position', ''); |
| | | css(el, 'top', ''); |
| | | css(el, 'left', ''); |
| | | css(el, 'width', ''); |
| | | css(el, 'height', ''); |
| | | } |
| | | |
| | | var expando = 'Sortable' + new Date().getTime(); |
| | | |
| | | function AnimationStateManager() { |
| | | var animationStates = [], |
| | | animationCallbackId; |
| | | return { |
| | | captureAnimationState: function captureAnimationState() { |
| | | animationStates = []; |
| | | if (!this.options.animation) return; |
| | | var children = [].slice.call(this.el.children); |
| | | children.forEach(function (child) { |
| | | if (css(child, 'display') === 'none' || child === Sortable.ghost) return; |
| | | animationStates.push({ |
| | | target: child, |
| | | rect: getRect(child) |
| | | }); |
| | | |
| | | var fromRect = _objectSpread({}, animationStates[animationStates.length - 1].rect); // If animating: compensate for current animation |
| | | |
| | | |
| | | if (child.thisAnimationDuration) { |
| | | var childMatrix = matrix(child, true); |
| | | |
| | | if (childMatrix) { |
| | | fromRect.top -= childMatrix.f; |
| | | fromRect.left -= childMatrix.e; |
| | | } |
| | | } |
| | | |
| | | child.fromRect = fromRect; |
| | | }); |
| | | }, |
| | | addAnimationState: function addAnimationState(state) { |
| | | animationStates.push(state); |
| | | }, |
| | | removeAnimationState: function removeAnimationState(target) { |
| | | animationStates.splice(indexOfObject(animationStates, { |
| | | target: target |
| | | }), 1); |
| | | }, |
| | | animateAll: function animateAll(callback) { |
| | | var _this = this; |
| | | |
| | | if (!this.options.animation) { |
| | | clearTimeout(animationCallbackId); |
| | | if (typeof callback === 'function') callback(); |
| | | return; |
| | | } |
| | | |
| | | var animating = false, |
| | | animationTime = 0; |
| | | animationStates.forEach(function (state) { |
| | | var time = 0, |
| | | target = state.target, |
| | | fromRect = target.fromRect, |
| | | toRect = getRect(target), |
| | | prevFromRect = target.prevFromRect, |
| | | prevToRect = target.prevToRect, |
| | | animatingRect = state.rect, |
| | | targetMatrix = matrix(target, true); |
| | | |
| | | if (targetMatrix) { |
| | | // Compensate for current animation |
| | | toRect.top -= targetMatrix.f; |
| | | toRect.left -= targetMatrix.e; |
| | | } |
| | | |
| | | target.toRect = toRect; |
| | | |
| | | if (target.thisAnimationDuration) { |
| | | // Could also check if animatingRect is between fromRect and toRect |
| | | if (isRectEqual(prevFromRect, toRect) && !isRectEqual(fromRect, toRect) && // Make sure animatingRect is on line between toRect & fromRect |
| | | (animatingRect.top - toRect.top) / (animatingRect.left - toRect.left) === (fromRect.top - toRect.top) / (fromRect.left - toRect.left)) { |
| | | // If returning to same place as started from animation and on same axis |
| | | time = calculateRealTime(animatingRect, prevFromRect, prevToRect, _this.options); |
| | | } |
| | | } // if fromRect != toRect: animate |
| | | |
| | | |
| | | if (!isRectEqual(toRect, fromRect)) { |
| | | target.prevFromRect = fromRect; |
| | | target.prevToRect = toRect; |
| | | |
| | | if (!time) { |
| | | time = _this.options.animation; |
| | | } |
| | | |
| | | _this.animate(target, animatingRect, toRect, time); |
| | | } |
| | | |
| | | if (time) { |
| | | animating = true; |
| | | animationTime = Math.max(animationTime, time); |
| | | clearTimeout(target.animationResetTimer); |
| | | target.animationResetTimer = setTimeout(function () { |
| | | target.animationTime = 0; |
| | | target.prevFromRect = null; |
| | | target.fromRect = null; |
| | | target.prevToRect = null; |
| | | target.thisAnimationDuration = null; |
| | | }, time); |
| | | target.thisAnimationDuration = time; |
| | | } |
| | | }); |
| | | clearTimeout(animationCallbackId); |
| | | |
| | | if (!animating) { |
| | | if (typeof callback === 'function') callback(); |
| | | } else { |
| | | animationCallbackId = setTimeout(function () { |
| | | if (typeof callback === 'function') callback(); |
| | | }, animationTime); |
| | | } |
| | | |
| | | animationStates = []; |
| | | }, |
| | | animate: function animate(target, currentRect, toRect, duration) { |
| | | if (duration) { |
| | | css(target, 'transition', ''); |
| | | css(target, 'transform', ''); |
| | | var elMatrix = matrix(this.el), |
| | | scaleX = elMatrix && elMatrix.a, |
| | | scaleY = elMatrix && elMatrix.d, |
| | | translateX = (currentRect.left - toRect.left) / (scaleX || 1), |
| | | translateY = (currentRect.top - toRect.top) / (scaleY || 1); |
| | | target.animatingX = !!translateX; |
| | | target.animatingY = !!translateY; |
| | | css(target, 'transform', 'translate3d(' + translateX + 'px,' + translateY + 'px,0)'); |
| | | repaint(target); // repaint |
| | | |
| | | css(target, 'transition', 'transform ' + duration + 'ms' + (this.options.easing ? ' ' + this.options.easing : '')); |
| | | css(target, 'transform', 'translate3d(0,0,0)'); |
| | | typeof target.animated === 'number' && clearTimeout(target.animated); |
| | | target.animated = setTimeout(function () { |
| | | css(target, 'transition', ''); |
| | | css(target, 'transform', ''); |
| | | target.animated = false; |
| | | target.animatingX = false; |
| | | target.animatingY = false; |
| | | }, duration); |
| | | } |
| | | } |
| | | }; |
| | | } |
| | | |
| | | function repaint(target) { |
| | | return target.offsetWidth; |
| | | } |
| | | |
| | | function calculateRealTime(animatingRect, fromRect, toRect, options) { |
| | | return Math.sqrt(Math.pow(fromRect.top - animatingRect.top, 2) + Math.pow(fromRect.left - animatingRect.left, 2)) / Math.sqrt(Math.pow(fromRect.top - toRect.top, 2) + Math.pow(fromRect.left - toRect.left, 2)) * options.animation; |
| | | } |
| | | |
| | | var plugins = []; |
| | | var defaults = { |
| | | initializeByDefault: true |
| | | }; |
| | | var PluginManager = { |
| | | mount: function mount(plugin) { |
| | | // Set default static properties |
| | | for (var option in defaults) { |
| | | if (defaults.hasOwnProperty(option) && !(option in plugin)) { |
| | | plugin[option] = defaults[option]; |
| | | } |
| | | } |
| | | |
| | | plugins.push(plugin); |
| | | }, |
| | | pluginEvent: function pluginEvent(eventName, sortable, evt) { |
| | | var _this = this; |
| | | |
| | | this.eventCanceled = false; |
| | | |
| | | evt.cancel = function () { |
| | | _this.eventCanceled = true; |
| | | }; |
| | | |
| | | var eventNameGlobal = eventName + 'Global'; |
| | | plugins.forEach(function (plugin) { |
| | | if (!sortable[plugin.pluginName]) return; // Fire global events if it exists in this sortable |
| | | |
| | | if (sortable[plugin.pluginName][eventNameGlobal]) { |
| | | sortable[plugin.pluginName][eventNameGlobal](_objectSpread({ |
| | | sortable: sortable |
| | | }, evt)); |
| | | } // Only fire plugin event if plugin is enabled in this sortable, |
| | | // and plugin has event defined |
| | | |
| | | |
| | | if (sortable.options[plugin.pluginName] && sortable[plugin.pluginName][eventName]) { |
| | | sortable[plugin.pluginName][eventName](_objectSpread({ |
| | | sortable: sortable |
| | | }, evt)); |
| | | } |
| | | }); |
| | | }, |
| | | initializePlugins: function initializePlugins(sortable, el, defaults, options) { |
| | | plugins.forEach(function (plugin) { |
| | | var pluginName = plugin.pluginName; |
| | | if (!sortable.options[pluginName] && !plugin.initializeByDefault) return; |
| | | var initialized = new plugin(sortable, el, sortable.options); |
| | | initialized.sortable = sortable; |
| | | initialized.options = sortable.options; |
| | | sortable[pluginName] = initialized; // Add default options from plugin |
| | | |
| | | _extends(defaults, initialized.defaults); |
| | | }); |
| | | |
| | | for (var option in sortable.options) { |
| | | if (!sortable.options.hasOwnProperty(option)) continue; |
| | | var modified = this.modifyOption(sortable, option, sortable.options[option]); |
| | | |
| | | if (typeof modified !== 'undefined') { |
| | | sortable.options[option] = modified; |
| | | } |
| | | } |
| | | }, |
| | | getEventProperties: function getEventProperties(name, sortable) { |
| | | var eventProperties = {}; |
| | | plugins.forEach(function (plugin) { |
| | | if (typeof plugin.eventProperties !== 'function') return; |
| | | |
| | | _extends(eventProperties, plugin.eventProperties.call(sortable[plugin.pluginName], name)); |
| | | }); |
| | | return eventProperties; |
| | | }, |
| | | modifyOption: function modifyOption(sortable, name, value) { |
| | | var modifiedValue; |
| | | plugins.forEach(function (plugin) { |
| | | // Plugin must exist on the Sortable |
| | | if (!sortable[plugin.pluginName]) return; // If static option listener exists for this option, call in the context of the Sortable's instance of this plugin |
| | | |
| | | if (plugin.optionListeners && typeof plugin.optionListeners[name] === 'function') { |
| | | modifiedValue = plugin.optionListeners[name].call(sortable[plugin.pluginName], value); |
| | | } |
| | | }); |
| | | return modifiedValue; |
| | | } |
| | | }; |
| | | |
| | | function dispatchEvent(_ref) { |
| | | var sortable = _ref.sortable, |
| | | rootEl = _ref.rootEl, |
| | | name = _ref.name, |
| | | targetEl = _ref.targetEl, |
| | | cloneEl = _ref.cloneEl, |
| | | toEl = _ref.toEl, |
| | | fromEl = _ref.fromEl, |
| | | oldIndex = _ref.oldIndex, |
| | | newIndex = _ref.newIndex, |
| | | oldDraggableIndex = _ref.oldDraggableIndex, |
| | | newDraggableIndex = _ref.newDraggableIndex, |
| | | originalEvent = _ref.originalEvent, |
| | | putSortable = _ref.putSortable, |
| | | extraEventProperties = _ref.extraEventProperties; |
| | | sortable = sortable || rootEl && rootEl[expando]; |
| | | if (!sortable) return; |
| | | var evt, |
| | | options = sortable.options, |
| | | onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1); // Support for new CustomEvent feature |
| | | |
| | | if (window.CustomEvent && !IE11OrLess && !Edge) { |
| | | evt = new CustomEvent(name, { |
| | | bubbles: true, |
| | | cancelable: true |
| | | }); |
| | | } else { |
| | | evt = document.createEvent('Event'); |
| | | evt.initEvent(name, true, true); |
| | | } |
| | | |
| | | evt.to = toEl || rootEl; |
| | | evt.from = fromEl || rootEl; |
| | | evt.item = targetEl || rootEl; |
| | | evt.clone = cloneEl; |
| | | evt.oldIndex = oldIndex; |
| | | evt.newIndex = newIndex; |
| | | evt.oldDraggableIndex = oldDraggableIndex; |
| | | evt.newDraggableIndex = newDraggableIndex; |
| | | evt.originalEvent = originalEvent; |
| | | evt.pullMode = putSortable ? putSortable.lastPutMode : undefined; |
| | | |
| | | var allEventProperties = _objectSpread({}, extraEventProperties, PluginManager.getEventProperties(name, sortable)); |
| | | |
| | | for (var option in allEventProperties) { |
| | | evt[option] = allEventProperties[option]; |
| | | } |
| | | |
| | | if (rootEl) { |
| | | rootEl.dispatchEvent(evt); |
| | | } |
| | | |
| | | if (options[onName]) { |
| | | options[onName].call(sortable, evt); |
| | | } |
| | | } |
| | | |
| | | var pluginEvent = function pluginEvent(eventName, sortable) { |
| | | var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, |
| | | originalEvent = _ref.evt, |
| | | data = _objectWithoutProperties(_ref, ["evt"]); |
| | | |
| | | PluginManager.pluginEvent.bind(Sortable)(eventName, sortable, _objectSpread({ |
| | | dragEl: dragEl, |
| | | parentEl: parentEl, |
| | | ghostEl: ghostEl, |
| | | rootEl: rootEl, |
| | | nextEl: nextEl, |
| | | lastDownEl: lastDownEl, |
| | | cloneEl: cloneEl, |
| | | cloneHidden: cloneHidden, |
| | | dragStarted: moved, |
| | | putSortable: putSortable, |
| | | activeSortable: Sortable.active, |
| | | originalEvent: originalEvent, |
| | | oldIndex: oldIndex, |
| | | oldDraggableIndex: oldDraggableIndex, |
| | | newIndex: newIndex, |
| | | newDraggableIndex: newDraggableIndex, |
| | | hideGhostForTarget: _hideGhostForTarget, |
| | | unhideGhostForTarget: _unhideGhostForTarget, |
| | | cloneNowHidden: function cloneNowHidden() { |
| | | cloneHidden = true; |
| | | }, |
| | | cloneNowShown: function cloneNowShown() { |
| | | cloneHidden = false; |
| | | }, |
| | | dispatchSortableEvent: function dispatchSortableEvent(name) { |
| | | _dispatchEvent({ |
| | | sortable: sortable, |
| | | name: name, |
| | | originalEvent: originalEvent |
| | | }); |
| | | } |
| | | }, data)); |
| | | }; |
| | | |
| | | function _dispatchEvent(info) { |
| | | dispatchEvent(_objectSpread({ |
| | | putSortable: putSortable, |
| | | cloneEl: cloneEl, |
| | | targetEl: dragEl, |
| | | rootEl: rootEl, |
| | | oldIndex: oldIndex, |
| | | oldDraggableIndex: oldDraggableIndex, |
| | | newIndex: newIndex, |
| | | newDraggableIndex: newDraggableIndex |
| | | }, info)); |
| | | } |
| | | |
| | | var dragEl, |
| | | parentEl, |
| | | ghostEl, |
| | | rootEl, |
| | | nextEl, |
| | | lastDownEl, |
| | | cloneEl, |
| | | cloneHidden, |
| | | oldIndex, |
| | | newIndex, |
| | | oldDraggableIndex, |
| | | newDraggableIndex, |
| | | activeGroup, |
| | | putSortable, |
| | | awaitingDragStarted = false, |
| | | ignoreNextClick = false, |
| | | sortables = [], |
| | | tapEvt, |
| | | touchEvt, |
| | | lastDx, |
| | | lastDy, |
| | | tapDistanceLeft, |
| | | tapDistanceTop, |
| | | moved, |
| | | lastTarget, |
| | | lastDirection, |
| | | pastFirstInvertThresh = false, |
| | | isCircumstantialInvert = false, |
| | | targetMoveDistance, |
| | | // For positioning ghost absolutely |
| | | ghostRelativeParent, |
| | | ghostRelativeParentInitialScroll = [], |
| | | // (left, top) |
| | | _silent = false, |
| | | savedInputChecked = []; |
| | | /** @const */ |
| | | |
| | | var documentExists = typeof document !== 'undefined', |
| | | PositionGhostAbsolutely = IOS, |
| | | CSSFloatProperty = Edge || IE11OrLess ? 'cssFloat' : 'float', |
| | | // This will not pass for IE9, because IE9 DnD only works on anchors |
| | | supportDraggable = documentExists && !ChromeForAndroid && !IOS && 'draggable' in document.createElement('div'), |
| | | supportCssPointerEvents = function () { |
| | | if (!documentExists) return; // false when <= IE11 |
| | | |
| | | if (IE11OrLess) { |
| | | return false; |
| | | } |
| | | |
| | | var el = document.createElement('x'); |
| | | el.style.cssText = 'pointer-events:auto'; |
| | | return el.style.pointerEvents === 'auto'; |
| | | }(), |
| | | _detectDirection = function _detectDirection(el, options) { |
| | | var elCSS = css(el), |
| | | elWidth = parseInt(elCSS.width) - parseInt(elCSS.paddingLeft) - parseInt(elCSS.paddingRight) - parseInt(elCSS.borderLeftWidth) - parseInt(elCSS.borderRightWidth), |
| | | child1 = getChild(el, 0, options), |
| | | child2 = getChild(el, 1, options), |
| | | firstChildCSS = child1 && css(child1), |
| | | secondChildCSS = child2 && css(child2), |
| | | firstChildWidth = firstChildCSS && parseInt(firstChildCSS.marginLeft) + parseInt(firstChildCSS.marginRight) + getRect(child1).width, |
| | | secondChildWidth = secondChildCSS && parseInt(secondChildCSS.marginLeft) + parseInt(secondChildCSS.marginRight) + getRect(child2).width; |
| | | |
| | | if (elCSS.display === 'flex') { |
| | | return elCSS.flexDirection === 'column' || elCSS.flexDirection === 'column-reverse' ? 'vertical' : 'horizontal'; |
| | | } |
| | | |
| | | if (elCSS.display === 'grid') { |
| | | return elCSS.gridTemplateColumns.split(' ').length <= 1 ? 'vertical' : 'horizontal'; |
| | | } |
| | | |
| | | if (child1 && firstChildCSS["float"] && firstChildCSS["float"] !== 'none') { |
| | | var touchingSideChild2 = firstChildCSS["float"] === 'left' ? 'left' : 'right'; |
| | | return child2 && (secondChildCSS.clear === 'both' || secondChildCSS.clear === touchingSideChild2) ? 'vertical' : 'horizontal'; |
| | | } |
| | | |
| | | return child1 && (firstChildCSS.display === 'block' || firstChildCSS.display === 'flex' || firstChildCSS.display === 'table' || firstChildCSS.display === 'grid' || firstChildWidth >= elWidth && elCSS[CSSFloatProperty] === 'none' || child2 && elCSS[CSSFloatProperty] === 'none' && firstChildWidth + secondChildWidth > elWidth) ? 'vertical' : 'horizontal'; |
| | | }, |
| | | _dragElInRowColumn = function _dragElInRowColumn(dragRect, targetRect, vertical) { |
| | | var dragElS1Opp = vertical ? dragRect.left : dragRect.top, |
| | | dragElS2Opp = vertical ? dragRect.right : dragRect.bottom, |
| | | dragElOppLength = vertical ? dragRect.width : dragRect.height, |
| | | targetS1Opp = vertical ? targetRect.left : targetRect.top, |
| | | targetS2Opp = vertical ? targetRect.right : targetRect.bottom, |
| | | targetOppLength = vertical ? targetRect.width : targetRect.height; |
| | | return dragElS1Opp === targetS1Opp || dragElS2Opp === targetS2Opp || dragElS1Opp + dragElOppLength / 2 === targetS1Opp + targetOppLength / 2; |
| | | }, |
| | | |
| | | /** |
| | | * Detects first nearest empty sortable to X and Y position using emptyInsertThreshold. |
| | | * @param {Number} x X position |
| | | * @param {Number} y Y position |
| | | * @return {HTMLElement} Element of the first found nearest Sortable |
| | | */ |
| | | _detectNearestEmptySortable = function _detectNearestEmptySortable(x, y) { |
| | | var ret; |
| | | sortables.some(function (sortable) { |
| | | if (lastChild(sortable)) return; |
| | | var rect = getRect(sortable), |
| | | threshold = sortable[expando].options.emptyInsertThreshold, |
| | | insideHorizontally = x >= rect.left - threshold && x <= rect.right + threshold, |
| | | insideVertically = y >= rect.top - threshold && y <= rect.bottom + threshold; |
| | | |
| | | if (threshold && insideHorizontally && insideVertically) { |
| | | return ret = sortable; |
| | | } |
| | | }); |
| | | return ret; |
| | | }, |
| | | _prepareGroup = function _prepareGroup(options) { |
| | | function toFn(value, pull) { |
| | | return function (to, from, dragEl, evt) { |
| | | var sameGroup = to.options.group.name && from.options.group.name && to.options.group.name === from.options.group.name; |
| | | |
| | | if (value == null && (pull || sameGroup)) { |
| | | // Default pull value |
| | | // Default pull and put value if same group |
| | | return true; |
| | | } else if (value == null || value === false) { |
| | | return false; |
| | | } else if (pull && value === 'clone') { |
| | | return value; |
| | | } else if (typeof value === 'function') { |
| | | return toFn(value(to, from, dragEl, evt), pull)(to, from, dragEl, evt); |
| | | } else { |
| | | var otherGroup = (pull ? to : from).options.group.name; |
| | | return value === true || typeof value === 'string' && value === otherGroup || value.join && value.indexOf(otherGroup) > -1; |
| | | } |
| | | }; |
| | | } |
| | | |
| | | var group = {}; |
| | | var originalGroup = options.group; |
| | | |
| | | if (!originalGroup || _typeof(originalGroup) != 'object') { |
| | | originalGroup = { |
| | | name: originalGroup |
| | | }; |
| | | } |
| | | |
| | | group.name = originalGroup.name; |
| | | group.checkPull = toFn(originalGroup.pull, true); |
| | | group.checkPut = toFn(originalGroup.put); |
| | | group.revertClone = originalGroup.revertClone; |
| | | options.group = group; |
| | | }, |
| | | _hideGhostForTarget = function _hideGhostForTarget() { |
| | | if (!supportCssPointerEvents && ghostEl) { |
| | | css(ghostEl, 'display', 'none'); |
| | | } |
| | | }, |
| | | _unhideGhostForTarget = function _unhideGhostForTarget() { |
| | | if (!supportCssPointerEvents && ghostEl) { |
| | | css(ghostEl, 'display', ''); |
| | | } |
| | | }; // #1184 fix - Prevent click event on fallback if dragged but item not changed position |
| | | |
| | | |
| | | if (documentExists) { |
| | | document.addEventListener('click', function (evt) { |
| | | if (ignoreNextClick) { |
| | | evt.preventDefault(); |
| | | evt.stopPropagation && evt.stopPropagation(); |
| | | evt.stopImmediatePropagation && evt.stopImmediatePropagation(); |
| | | ignoreNextClick = false; |
| | | return false; |
| | | } |
| | | }, true); |
| | | } |
| | | |
| | | var nearestEmptyInsertDetectEvent = function nearestEmptyInsertDetectEvent(evt) { |
| | | if (dragEl) { |
| | | evt = evt.touches ? evt.touches[0] : evt; |
| | | |
| | | var nearest = _detectNearestEmptySortable(evt.clientX, evt.clientY); |
| | | |
| | | if (nearest) { |
| | | // Create imitation event |
| | | var event = {}; |
| | | |
| | | for (var i in evt) { |
| | | if (evt.hasOwnProperty(i)) { |
| | | event[i] = evt[i]; |
| | | } |
| | | } |
| | | |
| | | event.target = event.rootEl = nearest; |
| | | event.preventDefault = void 0; |
| | | event.stopPropagation = void 0; |
| | | |
| | | nearest[expando]._onDragOver(event); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | var _checkOutsideTargetEl = function _checkOutsideTargetEl(evt) { |
| | | if (dragEl) { |
| | | dragEl.parentNode[expando]._isOutsideThisEl(evt.target); |
| | | } |
| | | }; |
| | | /** |
| | | * @class Sortable |
| | | * @param {HTMLElement} el |
| | | * @param {Object} [options] |
| | | */ |
| | | |
| | | |
| | | function Sortable(el, options) { |
| | | if (!(el && el.nodeType && el.nodeType === 1)) { |
| | | throw "Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(el)); |
| | | } |
| | | |
| | | this.el = el; // root element |
| | | |
| | | this.options = options = _extends({}, options); // Export instance |
| | | |
| | | el[expando] = this; |
| | | var defaults = { |
| | | group: null, |
| | | sort: true, |
| | | disabled: false, |
| | | store: null, |
| | | handle: null, |
| | | draggable: /^[uo]l$/i.test(el.nodeName) ? '>li' : '>*', |
| | | swapThreshold: 1, |
| | | // percentage; 0 <= x <= 1 |
| | | invertSwap: false, |
| | | // invert always |
| | | invertedSwapThreshold: null, |
| | | // will be set to same as swapThreshold if default |
| | | removeCloneOnHide: true, |
| | | direction: function direction() { |
| | | return _detectDirection(el, this.options); |
| | | }, |
| | | ghostClass: 'sortable-ghost', |
| | | chosenClass: 'sortable-chosen', |
| | | dragClass: 'sortable-drag', |
| | | ignore: 'a, img', |
| | | filter: null, |
| | | preventOnFilter: true, |
| | | animation: 0, |
| | | easing: null, |
| | | setData: function setData(dataTransfer, dragEl) { |
| | | dataTransfer.setData('Text', dragEl.textContent); |
| | | }, |
| | | dropBubble: false, |
| | | dragoverBubble: false, |
| | | dataIdAttr: 'data-id', |
| | | delay: 0, |
| | | delayOnTouchOnly: false, |
| | | touchStartThreshold: (Number.parseInt ? Number : window).parseInt(window.devicePixelRatio, 10) || 1, |
| | | forceFallback: false, |
| | | fallbackClass: 'sortable-fallback', |
| | | fallbackOnBody: false, |
| | | fallbackTolerance: 0, |
| | | fallbackOffset: { |
| | | x: 0, |
| | | y: 0 |
| | | }, |
| | | supportPointer: Sortable.supportPointer !== false && 'PointerEvent' in window, |
| | | emptyInsertThreshold: 5 |
| | | }; |
| | | PluginManager.initializePlugins(this, el, defaults); // Set default options |
| | | |
| | | for (var name in defaults) { |
| | | !(name in options) && (options[name] = defaults[name]); |
| | | } |
| | | |
| | | _prepareGroup(options); // Bind all private methods |
| | | |
| | | |
| | | for (var fn in this) { |
| | | if (fn.charAt(0) === '_' && typeof this[fn] === 'function') { |
| | | this[fn] = this[fn].bind(this); |
| | | } |
| | | } // Setup drag mode |
| | | |
| | | |
| | | this.nativeDraggable = options.forceFallback ? false : supportDraggable; |
| | | |
| | | if (this.nativeDraggable) { |
| | | // Touch start threshold cannot be greater than the native dragstart threshold |
| | | this.options.touchStartThreshold = 1; |
| | | } // Bind events |
| | | |
| | | |
| | | if (options.supportPointer) { |
| | | on(el, 'pointerdown', this._onTapStart); |
| | | } else { |
| | | on(el, 'mousedown', this._onTapStart); |
| | | on(el, 'touchstart', this._onTapStart); |
| | | } |
| | | |
| | | if (this.nativeDraggable) { |
| | | on(el, 'dragover', this); |
| | | on(el, 'dragenter', this); |
| | | } |
| | | |
| | | sortables.push(this.el); // Restore sorting |
| | | |
| | | options.store && options.store.get && this.sort(options.store.get(this) || []); // Add animation state manager |
| | | |
| | | _extends(this, AnimationStateManager()); |
| | | } |
| | | |
| | | Sortable.prototype = |
| | | /** @lends Sortable.prototype */ |
| | | { |
| | | constructor: Sortable, |
| | | _isOutsideThisEl: function _isOutsideThisEl(target) { |
| | | if (!this.el.contains(target) && target !== this.el) { |
| | | lastTarget = null; |
| | | } |
| | | }, |
| | | _getDirection: function _getDirection(evt, target) { |
| | | return typeof this.options.direction === 'function' ? this.options.direction.call(this, evt, target, dragEl) : this.options.direction; |
| | | }, |
| | | _onTapStart: function _onTapStart( |
| | | /** Event|TouchEvent */ |
| | | evt) { |
| | | if (!evt.cancelable) return; |
| | | |
| | | var _this = this, |
| | | el = this.el, |
| | | options = this.options, |
| | | preventOnFilter = options.preventOnFilter, |
| | | type = evt.type, |
| | | touch = evt.touches && evt.touches[0] || evt.pointerType && evt.pointerType === 'touch' && evt, |
| | | target = (touch || evt).target, |
| | | originalTarget = evt.target.shadowRoot && (evt.path && evt.path[0] || evt.composedPath && evt.composedPath()[0]) || target, |
| | | filter = options.filter; |
| | | |
| | | _saveInputCheckedState(el); // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group. |
| | | |
| | | |
| | | if (dragEl) { |
| | | return; |
| | | } |
| | | |
| | | if (/mousedown|pointerdown/.test(type) && evt.button !== 0 || options.disabled) { |
| | | return; // only left button and enabled |
| | | } // cancel dnd if original target is content editable |
| | | |
| | | |
| | | if (originalTarget.isContentEditable) { |
| | | return; |
| | | } |
| | | |
| | | target = closest(target, options.draggable, el, false); |
| | | |
| | | if (target && target.animated) { |
| | | return; |
| | | } |
| | | |
| | | if (lastDownEl === target) { |
| | | // Ignoring duplicate `down` |
| | | return; |
| | | } // Get the index of the dragged element within its parent |
| | | |
| | | |
| | | oldIndex = index(target); |
| | | oldDraggableIndex = index(target, options.draggable); // Check filter |
| | | |
| | | if (typeof filter === 'function') { |
| | | if (filter.call(this, evt, target, this)) { |
| | | _dispatchEvent({ |
| | | sortable: _this, |
| | | rootEl: originalTarget, |
| | | name: 'filter', |
| | | targetEl: target, |
| | | toEl: el, |
| | | fromEl: el |
| | | }); |
| | | |
| | | pluginEvent('filter', _this, { |
| | | evt: evt |
| | | }); |
| | | preventOnFilter && evt.cancelable && evt.preventDefault(); |
| | | return; // cancel dnd |
| | | } |
| | | } else if (filter) { |
| | | filter = filter.split(',').some(function (criteria) { |
| | | criteria = closest(originalTarget, criteria.trim(), el, false); |
| | | |
| | | if (criteria) { |
| | | _dispatchEvent({ |
| | | sortable: _this, |
| | | rootEl: criteria, |
| | | name: 'filter', |
| | | targetEl: target, |
| | | fromEl: el, |
| | | toEl: el |
| | | }); |
| | | |
| | | pluginEvent('filter', _this, { |
| | | evt: evt |
| | | }); |
| | | return true; |
| | | } |
| | | }); |
| | | |
| | | if (filter) { |
| | | preventOnFilter && evt.cancelable && evt.preventDefault(); |
| | | return; // cancel dnd |
| | | } |
| | | } |
| | | |
| | | if (options.handle && !closest(originalTarget, options.handle, el, false)) { |
| | | return; |
| | | } // Prepare `dragstart` |
| | | |
| | | |
| | | this._prepareDragStart(evt, touch, target); |
| | | }, |
| | | _prepareDragStart: function _prepareDragStart( |
| | | /** Event */ |
| | | evt, |
| | | /** Touch */ |
| | | touch, |
| | | /** HTMLElement */ |
| | | target) { |
| | | var _this = this, |
| | | el = _this.el, |
| | | options = _this.options, |
| | | ownerDocument = el.ownerDocument, |
| | | dragStartFn; |
| | | |
| | | if (target && !dragEl && target.parentNode === el) { |
| | | var dragRect = getRect(target); |
| | | rootEl = el; |
| | | dragEl = target; |
| | | parentEl = dragEl.parentNode; |
| | | nextEl = dragEl.nextSibling; |
| | | lastDownEl = target; |
| | | activeGroup = options.group; |
| | | Sortable.dragged = dragEl; |
| | | tapEvt = { |
| | | target: dragEl, |
| | | clientX: (touch || evt).clientX, |
| | | clientY: (touch || evt).clientY |
| | | }; |
| | | tapDistanceLeft = tapEvt.clientX - dragRect.left; |
| | | tapDistanceTop = tapEvt.clientY - dragRect.top; |
| | | this._lastX = (touch || evt).clientX; |
| | | this._lastY = (touch || evt).clientY; |
| | | dragEl.style['will-change'] = 'all'; |
| | | |
| | | dragStartFn = function dragStartFn() { |
| | | pluginEvent('delayEnded', _this, { |
| | | evt: evt |
| | | }); |
| | | |
| | | if (Sortable.eventCanceled) { |
| | | _this._onDrop(); |
| | | |
| | | return; |
| | | } // Delayed drag has been triggered |
| | | // we can re-enable the events: touchmove/mousemove |
| | | |
| | | |
| | | _this._disableDelayedDragEvents(); |
| | | |
| | | if (!FireFox && _this.nativeDraggable) { |
| | | dragEl.draggable = true; |
| | | } // Bind the events: dragstart/dragend |
| | | |
| | | |
| | | _this._triggerDragStart(evt, touch); // Drag start event |
| | | |
| | | |
| | | _dispatchEvent({ |
| | | sortable: _this, |
| | | name: 'choose', |
| | | originalEvent: evt |
| | | }); // Chosen item |
| | | |
| | | |
| | | toggleClass(dragEl, options.chosenClass, true); |
| | | }; // Disable "draggable" |
| | | |
| | | |
| | | options.ignore.split(',').forEach(function (criteria) { |
| | | find(dragEl, criteria.trim(), _disableDraggable); |
| | | }); |
| | | on(ownerDocument, 'dragover', nearestEmptyInsertDetectEvent); |
| | | on(ownerDocument, 'mousemove', nearestEmptyInsertDetectEvent); |
| | | on(ownerDocument, 'touchmove', nearestEmptyInsertDetectEvent); |
| | | on(ownerDocument, 'mouseup', _this._onDrop); |
| | | on(ownerDocument, 'touchend', _this._onDrop); |
| | | on(ownerDocument, 'touchcancel', _this._onDrop); // Make dragEl draggable (must be before delay for FireFox) |
| | | |
| | | if (FireFox && this.nativeDraggable) { |
| | | this.options.touchStartThreshold = 4; |
| | | dragEl.draggable = true; |
| | | } |
| | | |
| | | pluginEvent('delayStart', this, { |
| | | evt: evt |
| | | }); // Delay is impossible for native DnD in Edge or IE |
| | | |
| | | if (options.delay && (!options.delayOnTouchOnly || touch) && (!this.nativeDraggable || !(Edge || IE11OrLess))) { |
| | | if (Sortable.eventCanceled) { |
| | | this._onDrop(); |
| | | |
| | | return; |
| | | } // If the user moves the pointer or let go the click or touch |
| | | // before the delay has been reached: |
| | | // disable the delayed drag |
| | | |
| | | |
| | | on(ownerDocument, 'mouseup', _this._disableDelayedDrag); |
| | | on(ownerDocument, 'touchend', _this._disableDelayedDrag); |
| | | on(ownerDocument, 'touchcancel', _this._disableDelayedDrag); |
| | | on(ownerDocument, 'mousemove', _this._delayedDragTouchMoveHandler); |
| | | on(ownerDocument, 'touchmove', _this._delayedDragTouchMoveHandler); |
| | | options.supportPointer && on(ownerDocument, 'pointermove', _this._delayedDragTouchMoveHandler); |
| | | _this._dragStartTimer = setTimeout(dragStartFn, options.delay); |
| | | } else { |
| | | dragStartFn(); |
| | | } |
| | | } |
| | | }, |
| | | _delayedDragTouchMoveHandler: function _delayedDragTouchMoveHandler( |
| | | /** TouchEvent|PointerEvent **/ |
| | | e) { |
| | | var touch = e.touches ? e.touches[0] : e; |
| | | |
| | | if (Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) >= Math.floor(this.options.touchStartThreshold / (this.nativeDraggable && window.devicePixelRatio || 1))) { |
| | | this._disableDelayedDrag(); |
| | | } |
| | | }, |
| | | _disableDelayedDrag: function _disableDelayedDrag() { |
| | | dragEl && _disableDraggable(dragEl); |
| | | clearTimeout(this._dragStartTimer); |
| | | |
| | | this._disableDelayedDragEvents(); |
| | | }, |
| | | _disableDelayedDragEvents: function _disableDelayedDragEvents() { |
| | | var ownerDocument = this.el.ownerDocument; |
| | | off(ownerDocument, 'mouseup', this._disableDelayedDrag); |
| | | off(ownerDocument, 'touchend', this._disableDelayedDrag); |
| | | off(ownerDocument, 'touchcancel', this._disableDelayedDrag); |
| | | off(ownerDocument, 'mousemove', this._delayedDragTouchMoveHandler); |
| | | off(ownerDocument, 'touchmove', this._delayedDragTouchMoveHandler); |
| | | off(ownerDocument, 'pointermove', this._delayedDragTouchMoveHandler); |
| | | }, |
| | | _triggerDragStart: function _triggerDragStart( |
| | | /** Event */ |
| | | evt, |
| | | /** Touch */ |
| | | touch) { |
| | | touch = touch || evt.pointerType == 'touch' && evt; |
| | | |
| | | if (!this.nativeDraggable || touch) { |
| | | if (this.options.supportPointer) { |
| | | on(document, 'pointermove', this._onTouchMove); |
| | | } else if (touch) { |
| | | on(document, 'touchmove', this._onTouchMove); |
| | | } else { |
| | | on(document, 'mousemove', this._onTouchMove); |
| | | } |
| | | } else { |
| | | on(dragEl, 'dragend', this); |
| | | on(rootEl, 'dragstart', this._onDragStart); |
| | | } |
| | | |
| | | try { |
| | | if (document.selection) { |
| | | // Timeout neccessary for IE9 |
| | | _nextTick(function () { |
| | | document.selection.empty(); |
| | | }); |
| | | } else { |
| | | window.getSelection().removeAllRanges(); |
| | | } |
| | | } catch (err) {} |
| | | }, |
| | | _dragStarted: function _dragStarted(fallback, evt) { |
| | | |
| | | awaitingDragStarted = false; |
| | | |
| | | if (rootEl && dragEl) { |
| | | pluginEvent('dragStarted', this, { |
| | | evt: evt |
| | | }); |
| | | |
| | | if (this.nativeDraggable) { |
| | | on(document, 'dragover', _checkOutsideTargetEl); |
| | | } |
| | | |
| | | var options = this.options; // Apply effect |
| | | |
| | | !fallback && toggleClass(dragEl, options.dragClass, false); |
| | | toggleClass(dragEl, options.ghostClass, true); |
| | | Sortable.active = this; |
| | | fallback && this._appendGhost(); // Drag start event |
| | | |
| | | _dispatchEvent({ |
| | | sortable: this, |
| | | name: 'start', |
| | | originalEvent: evt |
| | | }); |
| | | } else { |
| | | this._nulling(); |
| | | } |
| | | }, |
| | | _emulateDragOver: function _emulateDragOver() { |
| | | if (touchEvt) { |
| | | this._lastX = touchEvt.clientX; |
| | | this._lastY = touchEvt.clientY; |
| | | |
| | | _hideGhostForTarget(); |
| | | |
| | | var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY); |
| | | var parent = target; |
| | | |
| | | while (target && target.shadowRoot) { |
| | | target = target.shadowRoot.elementFromPoint(touchEvt.clientX, touchEvt.clientY); |
| | | if (target === parent) break; |
| | | parent = target; |
| | | } |
| | | |
| | | dragEl.parentNode[expando]._isOutsideThisEl(target); |
| | | |
| | | if (parent) { |
| | | do { |
| | | if (parent[expando]) { |
| | | var inserted = void 0; |
| | | inserted = parent[expando]._onDragOver({ |
| | | clientX: touchEvt.clientX, |
| | | clientY: touchEvt.clientY, |
| | | target: target, |
| | | rootEl: parent |
| | | }); |
| | | |
| | | if (inserted && !this.options.dragoverBubble) { |
| | | break; |
| | | } |
| | | } |
| | | |
| | | target = parent; // store last element |
| | | } |
| | | /* jshint boss:true */ |
| | | while (parent = parent.parentNode); |
| | | } |
| | | |
| | | _unhideGhostForTarget(); |
| | | } |
| | | }, |
| | | _onTouchMove: function _onTouchMove( |
| | | /**TouchEvent*/ |
| | | evt) { |
| | | if (tapEvt) { |
| | | var options = this.options, |
| | | fallbackTolerance = options.fallbackTolerance, |
| | | fallbackOffset = options.fallbackOffset, |
| | | touch = evt.touches ? evt.touches[0] : evt, |
| | | ghostMatrix = ghostEl && matrix(ghostEl, true), |
| | | scaleX = ghostEl && ghostMatrix && ghostMatrix.a, |
| | | scaleY = ghostEl && ghostMatrix && ghostMatrix.d, |
| | | relativeScrollOffset = PositionGhostAbsolutely && ghostRelativeParent && getRelativeScrollOffset(ghostRelativeParent), |
| | | dx = (touch.clientX - tapEvt.clientX + fallbackOffset.x) / (scaleX || 1) + (relativeScrollOffset ? relativeScrollOffset[0] - ghostRelativeParentInitialScroll[0] : 0) / (scaleX || 1), |
| | | dy = (touch.clientY - tapEvt.clientY + fallbackOffset.y) / (scaleY || 1) + (relativeScrollOffset ? relativeScrollOffset[1] - ghostRelativeParentInitialScroll[1] : 0) / (scaleY || 1); // only set the status to dragging, when we are actually dragging |
| | | |
| | | if (!Sortable.active && !awaitingDragStarted) { |
| | | if (fallbackTolerance && Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) < fallbackTolerance) { |
| | | return; |
| | | } |
| | | |
| | | this._onDragStart(evt, true); |
| | | } |
| | | |
| | | if (ghostEl) { |
| | | if (ghostMatrix) { |
| | | ghostMatrix.e += dx - (lastDx || 0); |
| | | ghostMatrix.f += dy - (lastDy || 0); |
| | | } else { |
| | | ghostMatrix = { |
| | | a: 1, |
| | | b: 0, |
| | | c: 0, |
| | | d: 1, |
| | | e: dx, |
| | | f: dy |
| | | }; |
| | | } |
| | | |
| | | var cssMatrix = "matrix(".concat(ghostMatrix.a, ",").concat(ghostMatrix.b, ",").concat(ghostMatrix.c, ",").concat(ghostMatrix.d, ",").concat(ghostMatrix.e, ",").concat(ghostMatrix.f, ")"); |
| | | css(ghostEl, 'webkitTransform', cssMatrix); |
| | | css(ghostEl, 'mozTransform', cssMatrix); |
| | | css(ghostEl, 'msTransform', cssMatrix); |
| | | css(ghostEl, 'transform', cssMatrix); |
| | | lastDx = dx; |
| | | lastDy = dy; |
| | | touchEvt = touch; |
| | | } |
| | | |
| | | evt.cancelable && evt.preventDefault(); |
| | | } |
| | | }, |
| | | _appendGhost: function _appendGhost() { |
| | | // Bug if using scale(): https://stackoverflow.com/questions/2637058 |
| | | // Not being adjusted for |
| | | if (!ghostEl) { |
| | | var container = this.options.fallbackOnBody ? document.body : rootEl, |
| | | rect = getRect(dragEl, true, PositionGhostAbsolutely, true, container), |
| | | options = this.options; // Position absolutely |
| | | |
| | | if (PositionGhostAbsolutely) { |
| | | // Get relatively positioned parent |
| | | ghostRelativeParent = container; |
| | | |
| | | while (css(ghostRelativeParent, 'position') === 'static' && css(ghostRelativeParent, 'transform') === 'none' && ghostRelativeParent !== document) { |
| | | ghostRelativeParent = ghostRelativeParent.parentNode; |
| | | } |
| | | |
| | | if (ghostRelativeParent !== document.body && ghostRelativeParent !== document.documentElement) { |
| | | if (ghostRelativeParent === document) ghostRelativeParent = getWindowScrollingElement(); |
| | | rect.top += ghostRelativeParent.scrollTop; |
| | | rect.left += ghostRelativeParent.scrollLeft; |
| | | } else { |
| | | ghostRelativeParent = getWindowScrollingElement(); |
| | | } |
| | | |
| | | ghostRelativeParentInitialScroll = getRelativeScrollOffset(ghostRelativeParent); |
| | | } |
| | | |
| | | ghostEl = dragEl.cloneNode(true); |
| | | toggleClass(ghostEl, options.ghostClass, false); |
| | | toggleClass(ghostEl, options.fallbackClass, true); |
| | | toggleClass(ghostEl, options.dragClass, true); |
| | | css(ghostEl, 'transition', ''); |
| | | css(ghostEl, 'transform', ''); |
| | | css(ghostEl, 'box-sizing', 'border-box'); |
| | | css(ghostEl, 'margin', 0); |
| | | css(ghostEl, 'top', rect.top); |
| | | css(ghostEl, 'left', rect.left); |
| | | css(ghostEl, 'width', rect.width); |
| | | css(ghostEl, 'height', rect.height); |
| | | css(ghostEl, 'opacity', '0.8'); |
| | | css(ghostEl, 'position', PositionGhostAbsolutely ? 'absolute' : 'fixed'); |
| | | css(ghostEl, 'zIndex', '100000'); |
| | | css(ghostEl, 'pointerEvents', 'none'); |
| | | Sortable.ghost = ghostEl; |
| | | container.appendChild(ghostEl); // Set transform-origin |
| | | |
| | | css(ghostEl, 'transform-origin', tapDistanceLeft / parseInt(ghostEl.style.width) * 100 + '% ' + tapDistanceTop / parseInt(ghostEl.style.height) * 100 + '%'); |
| | | } |
| | | }, |
| | | _onDragStart: function _onDragStart( |
| | | /**Event*/ |
| | | evt, |
| | | /**boolean*/ |
| | | fallback) { |
| | | var _this = this; |
| | | |
| | | var dataTransfer = evt.dataTransfer; |
| | | var options = _this.options; |
| | | pluginEvent('dragStart', this, { |
| | | evt: evt |
| | | }); |
| | | |
| | | if (Sortable.eventCanceled) { |
| | | this._onDrop(); |
| | | |
| | | return; |
| | | } |
| | | |
| | | pluginEvent('setupClone', this); |
| | | |
| | | if (!Sortable.eventCanceled) { |
| | | cloneEl = clone(dragEl); |
| | | cloneEl.draggable = false; |
| | | cloneEl.style['will-change'] = ''; |
| | | |
| | | this._hideClone(); |
| | | |
| | | toggleClass(cloneEl, this.options.chosenClass, false); |
| | | Sortable.clone = cloneEl; |
| | | } // #1143: IFrame support workaround |
| | | |
| | | |
| | | _this.cloneId = _nextTick(function () { |
| | | pluginEvent('clone', _this); |
| | | if (Sortable.eventCanceled) return; |
| | | |
| | | if (!_this.options.removeCloneOnHide) { |
| | | rootEl.insertBefore(cloneEl, dragEl); |
| | | } |
| | | |
| | | _this._hideClone(); |
| | | |
| | | _dispatchEvent({ |
| | | sortable: _this, |
| | | name: 'clone' |
| | | }); |
| | | }); |
| | | !fallback && toggleClass(dragEl, options.dragClass, true); // Set proper drop events |
| | | |
| | | if (fallback) { |
| | | ignoreNextClick = true; |
| | | _this._loopId = setInterval(_this._emulateDragOver, 50); |
| | | } else { |
| | | // Undo what was set in _prepareDragStart before drag started |
| | | off(document, 'mouseup', _this._onDrop); |
| | | off(document, 'touchend', _this._onDrop); |
| | | off(document, 'touchcancel', _this._onDrop); |
| | | |
| | | if (dataTransfer) { |
| | | dataTransfer.effectAllowed = 'move'; |
| | | options.setData && options.setData.call(_this, dataTransfer, dragEl); |
| | | } |
| | | |
| | | on(document, 'drop', _this); // #1276 fix: |
| | | |
| | | css(dragEl, 'transform', 'translateZ(0)'); |
| | | } |
| | | |
| | | awaitingDragStarted = true; |
| | | _this._dragStartId = _nextTick(_this._dragStarted.bind(_this, fallback, evt)); |
| | | on(document, 'selectstart', _this); |
| | | moved = true; |
| | | |
| | | if (Safari) { |
| | | css(document.body, 'user-select', 'none'); |
| | | } |
| | | }, |
| | | // Returns true - if no further action is needed (either inserted or another condition) |
| | | _onDragOver: function _onDragOver( |
| | | /**Event*/ |
| | | evt) { |
| | | var el = this.el, |
| | | target = evt.target, |
| | | dragRect, |
| | | targetRect, |
| | | revert, |
| | | options = this.options, |
| | | group = options.group, |
| | | activeSortable = Sortable.active, |
| | | isOwner = activeGroup === group, |
| | | canSort = options.sort, |
| | | fromSortable = putSortable || activeSortable, |
| | | vertical, |
| | | _this = this, |
| | | completedFired = false; |
| | | |
| | | if (_silent) return; |
| | | |
| | | function dragOverEvent(name, extra) { |
| | | pluginEvent(name, _this, _objectSpread({ |
| | | evt: evt, |
| | | isOwner: isOwner, |
| | | axis: vertical ? 'vertical' : 'horizontal', |
| | | revert: revert, |
| | | dragRect: dragRect, |
| | | targetRect: targetRect, |
| | | canSort: canSort, |
| | | fromSortable: fromSortable, |
| | | target: target, |
| | | completed: completed, |
| | | onMove: function onMove(target, after) { |
| | | return _onMove(rootEl, el, dragEl, dragRect, target, getRect(target), evt, after); |
| | | }, |
| | | changed: changed |
| | | }, extra)); |
| | | } // Capture animation state |
| | | |
| | | |
| | | function capture() { |
| | | dragOverEvent('dragOverAnimationCapture'); |
| | | |
| | | _this.captureAnimationState(); |
| | | |
| | | if (_this !== fromSortable) { |
| | | fromSortable.captureAnimationState(); |
| | | } |
| | | } // Return invocation when dragEl is inserted (or completed) |
| | | |
| | | |
| | | function completed(insertion) { |
| | | dragOverEvent('dragOverCompleted', { |
| | | insertion: insertion |
| | | }); |
| | | |
| | | if (insertion) { |
| | | // Clones must be hidden before folding animation to capture dragRectAbsolute properly |
| | | if (isOwner) { |
| | | activeSortable._hideClone(); |
| | | } else { |
| | | activeSortable._showClone(_this); |
| | | } |
| | | |
| | | if (_this !== fromSortable) { |
| | | // Set ghost class to new sortable's ghost class |
| | | toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : activeSortable.options.ghostClass, false); |
| | | toggleClass(dragEl, options.ghostClass, true); |
| | | } |
| | | |
| | | if (putSortable !== _this && _this !== Sortable.active) { |
| | | putSortable = _this; |
| | | } else if (_this === Sortable.active && putSortable) { |
| | | putSortable = null; |
| | | } // Animation |
| | | |
| | | |
| | | if (fromSortable === _this) { |
| | | _this._ignoreWhileAnimating = target; |
| | | } |
| | | |
| | | _this.animateAll(function () { |
| | | dragOverEvent('dragOverAnimationComplete'); |
| | | _this._ignoreWhileAnimating = null; |
| | | }); |
| | | |
| | | if (_this !== fromSortable) { |
| | | fromSortable.animateAll(); |
| | | fromSortable._ignoreWhileAnimating = null; |
| | | } |
| | | } // Null lastTarget if it is not inside a previously swapped element |
| | | |
| | | |
| | | if (target === dragEl && !dragEl.animated || target === el && !target.animated) { |
| | | lastTarget = null; |
| | | } // no bubbling and not fallback |
| | | |
| | | |
| | | if (!options.dragoverBubble && !evt.rootEl && target !== document) { |
| | | dragEl.parentNode[expando]._isOutsideThisEl(evt.target); // Do not detect for empty insert if already inserted |
| | | |
| | | |
| | | !insertion && nearestEmptyInsertDetectEvent(evt); |
| | | } |
| | | |
| | | !options.dragoverBubble && evt.stopPropagation && evt.stopPropagation(); |
| | | return completedFired = true; |
| | | } // Call when dragEl has been inserted |
| | | |
| | | |
| | | function changed() { |
| | | newIndex = index(dragEl); |
| | | newDraggableIndex = index(dragEl, options.draggable); |
| | | |
| | | _dispatchEvent({ |
| | | sortable: _this, |
| | | name: 'change', |
| | | toEl: el, |
| | | newIndex: newIndex, |
| | | newDraggableIndex: newDraggableIndex, |
| | | originalEvent: evt |
| | | }); |
| | | } |
| | | |
| | | if (evt.preventDefault !== void 0) { |
| | | evt.cancelable && evt.preventDefault(); |
| | | } |
| | | |
| | | target = closest(target, options.draggable, el, true); |
| | | dragOverEvent('dragOver'); |
| | | if (Sortable.eventCanceled) return completedFired; |
| | | |
| | | if (dragEl.contains(evt.target) || target.animated && target.animatingX && target.animatingY || _this._ignoreWhileAnimating === target) { |
| | | return completed(false); |
| | | } |
| | | |
| | | ignoreNextClick = false; |
| | | |
| | | if (activeSortable && !options.disabled && (isOwner ? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list |
| | | : putSortable === this || (this.lastPutMode = activeGroup.checkPull(this, activeSortable, dragEl, evt)) && group.checkPut(this, activeSortable, dragEl, evt))) { |
| | | vertical = this._getDirection(evt, target) === 'vertical'; |
| | | dragRect = getRect(dragEl); |
| | | dragOverEvent('dragOverValid'); |
| | | if (Sortable.eventCanceled) return completedFired; |
| | | |
| | | if (revert) { |
| | | parentEl = rootEl; // actualization |
| | | |
| | | capture(); |
| | | |
| | | this._hideClone(); |
| | | |
| | | dragOverEvent('revert'); |
| | | |
| | | if (!Sortable.eventCanceled) { |
| | | if (nextEl) { |
| | | rootEl.insertBefore(dragEl, nextEl); |
| | | } else { |
| | | rootEl.appendChild(dragEl); |
| | | } |
| | | } |
| | | |
| | | return completed(true); |
| | | } |
| | | |
| | | var elLastChild = lastChild(el, options.draggable); |
| | | |
| | | if (!elLastChild || _ghostIsLast(evt, vertical, this) && !elLastChild.animated) { |
| | | // If already at end of list: Do not insert |
| | | if (elLastChild === dragEl) { |
| | | return completed(false); |
| | | } // assign target only if condition is true |
| | | |
| | | |
| | | if (elLastChild && el === evt.target) { |
| | | target = elLastChild; |
| | | } |
| | | |
| | | if (target) { |
| | | targetRect = getRect(target); |
| | | } |
| | | |
| | | if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, !!target) !== false) { |
| | | capture(); |
| | | el.appendChild(dragEl); |
| | | parentEl = el; // actualization |
| | | |
| | | changed(); |
| | | return completed(true); |
| | | } |
| | | } else if (target.parentNode === el) { |
| | | targetRect = getRect(target); |
| | | var direction = 0, |
| | | targetBeforeFirstSwap, |
| | | differentLevel = dragEl.parentNode !== el, |
| | | differentRowCol = !_dragElInRowColumn(dragEl.animated && dragEl.toRect || dragRect, target.animated && target.toRect || targetRect, vertical), |
| | | side1 = vertical ? 'top' : 'left', |
| | | scrolledPastTop = isScrolledPast(target, 'top', 'top') || isScrolledPast(dragEl, 'top', 'top'), |
| | | scrollBefore = scrolledPastTop ? scrolledPastTop.scrollTop : void 0; |
| | | |
| | | if (lastTarget !== target) { |
| | | targetBeforeFirstSwap = targetRect[side1]; |
| | | pastFirstInvertThresh = false; |
| | | isCircumstantialInvert = !differentRowCol && options.invertSwap || differentLevel; |
| | | } |
| | | |
| | | direction = _getSwapDirection(evt, target, targetRect, vertical, differentRowCol ? 1 : options.swapThreshold, options.invertedSwapThreshold == null ? options.swapThreshold : options.invertedSwapThreshold, isCircumstantialInvert, lastTarget === target); |
| | | var sibling; |
| | | |
| | | if (direction !== 0) { |
| | | // Check if target is beside dragEl in respective direction (ignoring hidden elements) |
| | | var dragIndex = index(dragEl); |
| | | |
| | | do { |
| | | dragIndex -= direction; |
| | | sibling = parentEl.children[dragIndex]; |
| | | } while (sibling && (css(sibling, 'display') === 'none' || sibling === ghostEl)); |
| | | } // If dragEl is already beside target: Do not insert |
| | | |
| | | |
| | | if (direction === 0 || sibling === target) { |
| | | return completed(false); |
| | | } |
| | | |
| | | lastTarget = target; |
| | | lastDirection = direction; |
| | | var nextSibling = target.nextElementSibling, |
| | | after = false; |
| | | after = direction === 1; |
| | | |
| | | var moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after); |
| | | |
| | | if (moveVector !== false) { |
| | | if (moveVector === 1 || moveVector === -1) { |
| | | after = moveVector === 1; |
| | | } |
| | | |
| | | _silent = true; |
| | | setTimeout(_unsilent, 30); |
| | | capture(); |
| | | |
| | | if (after && !nextSibling) { |
| | | el.appendChild(dragEl); |
| | | } else { |
| | | target.parentNode.insertBefore(dragEl, after ? nextSibling : target); |
| | | } // Undo chrome's scroll adjustment (has no effect on other browsers) |
| | | |
| | | |
| | | if (scrolledPastTop) { |
| | | scrollBy(scrolledPastTop, 0, scrollBefore - scrolledPastTop.scrollTop); |
| | | } |
| | | |
| | | parentEl = dragEl.parentNode; // actualization |
| | | // must be done before animation |
| | | |
| | | if (targetBeforeFirstSwap !== undefined && !isCircumstantialInvert) { |
| | | targetMoveDistance = Math.abs(targetBeforeFirstSwap - getRect(target)[side1]); |
| | | } |
| | | |
| | | changed(); |
| | | return completed(true); |
| | | } |
| | | } |
| | | |
| | | if (el.contains(dragEl)) { |
| | | return completed(false); |
| | | } |
| | | } |
| | | |
| | | return false; |
| | | }, |
| | | _ignoreWhileAnimating: null, |
| | | _offMoveEvents: function _offMoveEvents() { |
| | | off(document, 'mousemove', this._onTouchMove); |
| | | off(document, 'touchmove', this._onTouchMove); |
| | | off(document, 'pointermove', this._onTouchMove); |
| | | off(document, 'dragover', nearestEmptyInsertDetectEvent); |
| | | off(document, 'mousemove', nearestEmptyInsertDetectEvent); |
| | | off(document, 'touchmove', nearestEmptyInsertDetectEvent); |
| | | }, |
| | | _offUpEvents: function _offUpEvents() { |
| | | var ownerDocument = this.el.ownerDocument; |
| | | off(ownerDocument, 'mouseup', this._onDrop); |
| | | off(ownerDocument, 'touchend', this._onDrop); |
| | | off(ownerDocument, 'pointerup', this._onDrop); |
| | | off(ownerDocument, 'touchcancel', this._onDrop); |
| | | off(document, 'selectstart', this); |
| | | }, |
| | | _onDrop: function _onDrop( |
| | | /**Event*/ |
| | | evt) { |
| | | var el = this.el, |
| | | options = this.options; // Get the index of the dragged element within its parent |
| | | |
| | | newIndex = index(dragEl); |
| | | newDraggableIndex = index(dragEl, options.draggable); |
| | | pluginEvent('drop', this, { |
| | | evt: evt |
| | | }); |
| | | parentEl = dragEl && dragEl.parentNode; // Get again after plugin event |
| | | |
| | | newIndex = index(dragEl); |
| | | newDraggableIndex = index(dragEl, options.draggable); |
| | | |
| | | if (Sortable.eventCanceled) { |
| | | this._nulling(); |
| | | |
| | | return; |
| | | } |
| | | |
| | | awaitingDragStarted = false; |
| | | isCircumstantialInvert = false; |
| | | pastFirstInvertThresh = false; |
| | | clearInterval(this._loopId); |
| | | clearTimeout(this._dragStartTimer); |
| | | |
| | | _cancelNextTick(this.cloneId); |
| | | |
| | | _cancelNextTick(this._dragStartId); // Unbind events |
| | | |
| | | |
| | | if (this.nativeDraggable) { |
| | | off(document, 'drop', this); |
| | | off(el, 'dragstart', this._onDragStart); |
| | | } |
| | | |
| | | this._offMoveEvents(); |
| | | |
| | | this._offUpEvents(); |
| | | |
| | | if (Safari) { |
| | | css(document.body, 'user-select', ''); |
| | | } |
| | | |
| | | css(dragEl, 'transform', ''); |
| | | |
| | | if (evt) { |
| | | if (moved) { |
| | | evt.cancelable && evt.preventDefault(); |
| | | !options.dropBubble && evt.stopPropagation(); |
| | | } |
| | | |
| | | ghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl); |
| | | |
| | | if (rootEl === parentEl || putSortable && putSortable.lastPutMode !== 'clone') { |
| | | // Remove clone(s) |
| | | cloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl); |
| | | } |
| | | |
| | | if (dragEl) { |
| | | if (this.nativeDraggable) { |
| | | off(dragEl, 'dragend', this); |
| | | } |
| | | |
| | | _disableDraggable(dragEl); |
| | | |
| | | dragEl.style['will-change'] = ''; // Remove classes |
| | | // ghostClass is added in dragStarted |
| | | |
| | | if (moved && !awaitingDragStarted) { |
| | | toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : this.options.ghostClass, false); |
| | | } |
| | | |
| | | toggleClass(dragEl, this.options.chosenClass, false); // Drag stop event |
| | | |
| | | _dispatchEvent({ |
| | | sortable: this, |
| | | name: 'unchoose', |
| | | toEl: parentEl, |
| | | newIndex: null, |
| | | newDraggableIndex: null, |
| | | originalEvent: evt |
| | | }); |
| | | |
| | | if (rootEl !== parentEl) { |
| | | if (newIndex >= 0) { |
| | | // Add event |
| | | _dispatchEvent({ |
| | | rootEl: parentEl, |
| | | name: 'add', |
| | | toEl: parentEl, |
| | | fromEl: rootEl, |
| | | originalEvent: evt |
| | | }); // Remove event |
| | | |
| | | |
| | | _dispatchEvent({ |
| | | sortable: this, |
| | | name: 'remove', |
| | | toEl: parentEl, |
| | | originalEvent: evt |
| | | }); // drag from one list and drop into another |
| | | |
| | | |
| | | _dispatchEvent({ |
| | | rootEl: parentEl, |
| | | name: 'sort', |
| | | toEl: parentEl, |
| | | fromEl: rootEl, |
| | | originalEvent: evt |
| | | }); |
| | | |
| | | _dispatchEvent({ |
| | | sortable: this, |
| | | name: 'sort', |
| | | toEl: parentEl, |
| | | originalEvent: evt |
| | | }); |
| | | } |
| | | |
| | | putSortable && putSortable.save(); |
| | | } else { |
| | | if (newIndex !== oldIndex) { |
| | | if (newIndex >= 0) { |
| | | // drag & drop within the same list |
| | | _dispatchEvent({ |
| | | sortable: this, |
| | | name: 'update', |
| | | toEl: parentEl, |
| | | originalEvent: evt |
| | | }); |
| | | |
| | | _dispatchEvent({ |
| | | sortable: this, |
| | | name: 'sort', |
| | | toEl: parentEl, |
| | | originalEvent: evt |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (Sortable.active) { |
| | | /* jshint eqnull:true */ |
| | | if (newIndex == null || newIndex === -1) { |
| | | newIndex = oldIndex; |
| | | newDraggableIndex = oldDraggableIndex; |
| | | } |
| | | |
| | | _dispatchEvent({ |
| | | sortable: this, |
| | | name: 'end', |
| | | toEl: parentEl, |
| | | originalEvent: evt |
| | | }); // Save sorting |
| | | |
| | | |
| | | this.save(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | this._nulling(); |
| | | }, |
| | | _nulling: function _nulling() { |
| | | pluginEvent('nulling', this); |
| | | rootEl = dragEl = parentEl = ghostEl = nextEl = cloneEl = lastDownEl = cloneHidden = tapEvt = touchEvt = moved = newIndex = newDraggableIndex = oldIndex = oldDraggableIndex = lastTarget = lastDirection = putSortable = activeGroup = Sortable.dragged = Sortable.ghost = Sortable.clone = Sortable.active = null; |
| | | savedInputChecked.forEach(function (el) { |
| | | el.checked = true; |
| | | }); |
| | | savedInputChecked.length = lastDx = lastDy = 0; |
| | | }, |
| | | handleEvent: function handleEvent( |
| | | /**Event*/ |
| | | evt) { |
| | | switch (evt.type) { |
| | | case 'drop': |
| | | case 'dragend': |
| | | this._onDrop(evt); |
| | | |
| | | break; |
| | | |
| | | case 'dragenter': |
| | | case 'dragover': |
| | | if (dragEl) { |
| | | this._onDragOver(evt); |
| | | |
| | | _globalDragOver(evt); |
| | | } |
| | | |
| | | break; |
| | | |
| | | case 'selectstart': |
| | | evt.preventDefault(); |
| | | break; |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * Serializes the item into an array of string. |
| | | * @returns {String[]} |
| | | */ |
| | | toArray: function toArray() { |
| | | var order = [], |
| | | el, |
| | | children = this.el.children, |
| | | i = 0, |
| | | n = children.length, |
| | | options = this.options; |
| | | |
| | | for (; i < n; i++) { |
| | | el = children[i]; |
| | | |
| | | if (closest(el, options.draggable, this.el, false)) { |
| | | order.push(el.getAttribute(options.dataIdAttr) || _generateId(el)); |
| | | } |
| | | } |
| | | |
| | | return order; |
| | | }, |
| | | |
| | | /** |
| | | * Sorts the elements according to the array. |
| | | * @param {String[]} order order of the items |
| | | */ |
| | | sort: function sort(order) { |
| | | var items = {}, |
| | | rootEl = this.el; |
| | | this.toArray().forEach(function (id, i) { |
| | | var el = rootEl.children[i]; |
| | | |
| | | if (closest(el, this.options.draggable, rootEl, false)) { |
| | | items[id] = el; |
| | | } |
| | | }, this); |
| | | order.forEach(function (id) { |
| | | if (items[id]) { |
| | | rootEl.removeChild(items[id]); |
| | | rootEl.appendChild(items[id]); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * Save the current sorting |
| | | */ |
| | | save: function save() { |
| | | var store = this.options.store; |
| | | store && store.set && store.set(this); |
| | | }, |
| | | |
| | | /** |
| | | * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree. |
| | | * @param {HTMLElement} el |
| | | * @param {String} [selector] default: `options.draggable` |
| | | * @returns {HTMLElement|null} |
| | | */ |
| | | closest: function closest$1(el, selector) { |
| | | return closest(el, selector || this.options.draggable, this.el, false); |
| | | }, |
| | | |
| | | /** |
| | | * Set/get option |
| | | * @param {string} name |
| | | * @param {*} [value] |
| | | * @returns {*} |
| | | */ |
| | | option: function option(name, value) { |
| | | var options = this.options; |
| | | |
| | | if (value === void 0) { |
| | | return options[name]; |
| | | } else { |
| | | var modifiedValue = PluginManager.modifyOption(this, name, value); |
| | | |
| | | if (typeof modifiedValue !== 'undefined') { |
| | | options[name] = modifiedValue; |
| | | } else { |
| | | options[name] = value; |
| | | } |
| | | |
| | | if (name === 'group') { |
| | | _prepareGroup(options); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * Destroy |
| | | */ |
| | | destroy: function destroy() { |
| | | pluginEvent('destroy', this); |
| | | var el = this.el; |
| | | el[expando] = null; |
| | | off(el, 'mousedown', this._onTapStart); |
| | | off(el, 'touchstart', this._onTapStart); |
| | | off(el, 'pointerdown', this._onTapStart); |
| | | |
| | | if (this.nativeDraggable) { |
| | | off(el, 'dragover', this); |
| | | off(el, 'dragenter', this); |
| | | } // Remove draggable attributes |
| | | |
| | | |
| | | Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) { |
| | | el.removeAttribute('draggable'); |
| | | }); |
| | | |
| | | this._onDrop(); |
| | | |
| | | this._disableDelayedDragEvents(); |
| | | |
| | | sortables.splice(sortables.indexOf(this.el), 1); |
| | | this.el = el = null; |
| | | }, |
| | | _hideClone: function _hideClone() { |
| | | if (!cloneHidden) { |
| | | pluginEvent('hideClone', this); |
| | | if (Sortable.eventCanceled) return; |
| | | css(cloneEl, 'display', 'none'); |
| | | |
| | | if (this.options.removeCloneOnHide && cloneEl.parentNode) { |
| | | cloneEl.parentNode.removeChild(cloneEl); |
| | | } |
| | | |
| | | cloneHidden = true; |
| | | } |
| | | }, |
| | | _showClone: function _showClone(putSortable) { |
| | | if (putSortable.lastPutMode !== 'clone') { |
| | | this._hideClone(); |
| | | |
| | | return; |
| | | } |
| | | |
| | | if (cloneHidden) { |
| | | pluginEvent('showClone', this); |
| | | if (Sortable.eventCanceled) return; // show clone at dragEl or original position |
| | | |
| | | if (rootEl.contains(dragEl) && !this.options.group.revertClone) { |
| | | rootEl.insertBefore(cloneEl, dragEl); |
| | | } else if (nextEl) { |
| | | rootEl.insertBefore(cloneEl, nextEl); |
| | | } else { |
| | | rootEl.appendChild(cloneEl); |
| | | } |
| | | |
| | | if (this.options.group.revertClone) { |
| | | this.animate(dragEl, cloneEl); |
| | | } |
| | | |
| | | css(cloneEl, 'display', ''); |
| | | cloneHidden = false; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | function _globalDragOver( |
| | | /**Event*/ |
| | | evt) { |
| | | if (evt.dataTransfer) { |
| | | evt.dataTransfer.dropEffect = 'move'; |
| | | } |
| | | |
| | | evt.cancelable && evt.preventDefault(); |
| | | } |
| | | |
| | | function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvent, willInsertAfter) { |
| | | var evt, |
| | | sortable = fromEl[expando], |
| | | onMoveFn = sortable.options.onMove, |
| | | retVal; // Support for new CustomEvent feature |
| | | |
| | | if (window.CustomEvent && !IE11OrLess && !Edge) { |
| | | evt = new CustomEvent('move', { |
| | | bubbles: true, |
| | | cancelable: true |
| | | }); |
| | | } else { |
| | | evt = document.createEvent('Event'); |
| | | evt.initEvent('move', true, true); |
| | | } |
| | | |
| | | evt.to = toEl; |
| | | evt.from = fromEl; |
| | | evt.dragged = dragEl; |
| | | evt.draggedRect = dragRect; |
| | | evt.related = targetEl || toEl; |
| | | evt.relatedRect = targetRect || getRect(toEl); |
| | | evt.willInsertAfter = willInsertAfter; |
| | | evt.originalEvent = originalEvent; |
| | | fromEl.dispatchEvent(evt); |
| | | |
| | | if (onMoveFn) { |
| | | retVal = onMoveFn.call(sortable, evt, originalEvent); |
| | | } |
| | | |
| | | return retVal; |
| | | } |
| | | |
| | | function _disableDraggable(el) { |
| | | el.draggable = false; |
| | | } |
| | | |
| | | function _unsilent() { |
| | | _silent = false; |
| | | } |
| | | |
| | | function _ghostIsLast(evt, vertical, sortable) { |
| | | var rect = getRect(lastChild(sortable.el, sortable.options.draggable)); |
| | | var spacer = 10; |
| | | return vertical ? evt.clientX > rect.right + spacer || evt.clientX <= rect.right && evt.clientY > rect.bottom && evt.clientX >= rect.left : evt.clientX > rect.right && evt.clientY > rect.top || evt.clientX <= rect.right && evt.clientY > rect.bottom + spacer; |
| | | } |
| | | |
| | | function _getSwapDirection(evt, target, targetRect, vertical, swapThreshold, invertedSwapThreshold, invertSwap, isLastTarget) { |
| | | var mouseOnAxis = vertical ? evt.clientY : evt.clientX, |
| | | targetLength = vertical ? targetRect.height : targetRect.width, |
| | | targetS1 = vertical ? targetRect.top : targetRect.left, |
| | | targetS2 = vertical ? targetRect.bottom : targetRect.right, |
| | | invert = false; |
| | | |
| | | if (!invertSwap) { |
| | | // Never invert or create dragEl shadow when target movemenet causes mouse to move past the end of regular swapThreshold |
| | | if (isLastTarget && targetMoveDistance < targetLength * swapThreshold) { |
| | | // multiplied only by swapThreshold because mouse will already be inside target by (1 - threshold) * targetLength / 2 |
| | | // check if past first invert threshold on side opposite of lastDirection |
| | | if (!pastFirstInvertThresh && (lastDirection === 1 ? mouseOnAxis > targetS1 + targetLength * invertedSwapThreshold / 2 : mouseOnAxis < targetS2 - targetLength * invertedSwapThreshold / 2)) { |
| | | // past first invert threshold, do not restrict inverted threshold to dragEl shadow |
| | | pastFirstInvertThresh = true; |
| | | } |
| | | |
| | | if (!pastFirstInvertThresh) { |
| | | // dragEl shadow (target move distance shadow) |
| | | if (lastDirection === 1 ? mouseOnAxis < targetS1 + targetMoveDistance // over dragEl shadow |
| | | : mouseOnAxis > targetS2 - targetMoveDistance) { |
| | | return -lastDirection; |
| | | } |
| | | } else { |
| | | invert = true; |
| | | } |
| | | } else { |
| | | // Regular |
| | | if (mouseOnAxis > targetS1 + targetLength * (1 - swapThreshold) / 2 && mouseOnAxis < targetS2 - targetLength * (1 - swapThreshold) / 2) { |
| | | return _getInsertDirection(target); |
| | | } |
| | | } |
| | | } |
| | | |
| | | invert = invert || invertSwap; |
| | | |
| | | if (invert) { |
| | | // Invert of regular |
| | | if (mouseOnAxis < targetS1 + targetLength * invertedSwapThreshold / 2 || mouseOnAxis > targetS2 - targetLength * invertedSwapThreshold / 2) { |
| | | return mouseOnAxis > targetS1 + targetLength / 2 ? 1 : -1; |
| | | } |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | /** |
| | | * Gets the direction dragEl must be swapped relative to target in order to make it |
| | | * seem that dragEl has been "inserted" into that element's position |
| | | * @param {HTMLElement} target The target whose position dragEl is being inserted at |
| | | * @return {Number} Direction dragEl must be swapped |
| | | */ |
| | | |
| | | |
| | | function _getInsertDirection(target) { |
| | | if (index(dragEl) < index(target)) { |
| | | return 1; |
| | | } else { |
| | | return -1; |
| | | } |
| | | } |
| | | /** |
| | | * Generate id |
| | | * @param {HTMLElement} el |
| | | * @returns {String} |
| | | * @private |
| | | */ |
| | | |
| | | |
| | | function _generateId(el) { |
| | | var str = el.tagName + el.className + el.src + el.href + el.textContent, |
| | | i = str.length, |
| | | sum = 0; |
| | | |
| | | while (i--) { |
| | | sum += str.charCodeAt(i); |
| | | } |
| | | |
| | | return sum.toString(36); |
| | | } |
| | | |
| | | function _saveInputCheckedState(root) { |
| | | savedInputChecked.length = 0; |
| | | var inputs = root.getElementsByTagName('input'); |
| | | var idx = inputs.length; |
| | | |
| | | while (idx--) { |
| | | var el = inputs[idx]; |
| | | el.checked && savedInputChecked.push(el); |
| | | } |
| | | } |
| | | |
| | | function _nextTick(fn) { |
| | | return setTimeout(fn, 0); |
| | | } |
| | | |
| | | function _cancelNextTick(id) { |
| | | return clearTimeout(id); |
| | | } // Fixed #973: |
| | | |
| | | |
| | | if (documentExists) { |
| | | on(document, 'touchmove', function (evt) { |
| | | if ((Sortable.active || awaitingDragStarted) && evt.cancelable) { |
| | | evt.preventDefault(); |
| | | } |
| | | }); |
| | | } // Export utils |
| | | |
| | | |
| | | Sortable.utils = { |
| | | on: on, |
| | | off: off, |
| | | css: css, |
| | | find: find, |
| | | is: function is(el, selector) { |
| | | return !!closest(el, selector, el, false); |
| | | }, |
| | | extend: extend, |
| | | throttle: throttle, |
| | | closest: closest, |
| | | toggleClass: toggleClass, |
| | | clone: clone, |
| | | index: index, |
| | | nextTick: _nextTick, |
| | | cancelNextTick: _cancelNextTick, |
| | | detectDirection: _detectDirection, |
| | | getChild: getChild |
| | | }; |
| | | /** |
| | | * Get the Sortable instance of an element |
| | | * @param {HTMLElement} element The element |
| | | * @return {Sortable|undefined} The instance of Sortable |
| | | */ |
| | | |
| | | Sortable.get = function (element) { |
| | | return element[expando]; |
| | | }; |
| | | /** |
| | | * Mount a plugin to Sortable |
| | | * @param {...SortablePlugin|SortablePlugin[]} plugins Plugins being mounted |
| | | */ |
| | | |
| | | |
| | | Sortable.mount = function () { |
| | | for (var _len = arguments.length, plugins = new Array(_len), _key = 0; _key < _len; _key++) { |
| | | plugins[_key] = arguments[_key]; |
| | | } |
| | | |
| | | if (plugins[0].constructor === Array) plugins = plugins[0]; |
| | | plugins.forEach(function (plugin) { |
| | | if (!plugin.prototype || !plugin.prototype.constructor) { |
| | | throw "Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(plugin)); |
| | | } |
| | | |
| | | if (plugin.utils) Sortable.utils = _objectSpread({}, Sortable.utils, plugin.utils); |
| | | PluginManager.mount(plugin); |
| | | }); |
| | | }; |
| | | /** |
| | | * Create sortable instance |
| | | * @param {HTMLElement} el |
| | | * @param {Object} [options] |
| | | */ |
| | | |
| | | |
| | | Sortable.create = function (el, options) { |
| | | return new Sortable(el, options); |
| | | }; // Export |
| | | |
| | | |
| | | Sortable.version = version; |
| | | |
| | | var autoScrolls = [], |
| | | scrollEl, |
| | | scrollRootEl, |
| | | scrolling = false, |
| | | lastAutoScrollX, |
| | | lastAutoScrollY, |
| | | touchEvt$1, |
| | | pointerElemChangedInterval; |
| | | |
| | | function AutoScrollPlugin() { |
| | | function AutoScroll() { |
| | | this.defaults = { |
| | | scroll: true, |
| | | scrollSensitivity: 30, |
| | | scrollSpeed: 10, |
| | | bubbleScroll: true |
| | | }; // Bind all private methods |
| | | |
| | | for (var fn in this) { |
| | | if (fn.charAt(0) === '_' && typeof this[fn] === 'function') { |
| | | this[fn] = this[fn].bind(this); |
| | | } |
| | | } |
| | | } |
| | | |
| | | AutoScroll.prototype = { |
| | | dragStarted: function dragStarted(_ref) { |
| | | var originalEvent = _ref.originalEvent; |
| | | |
| | | if (this.sortable.nativeDraggable) { |
| | | on(document, 'dragover', this._handleAutoScroll); |
| | | } else { |
| | | if (this.options.supportPointer) { |
| | | on(document, 'pointermove', this._handleFallbackAutoScroll); |
| | | } else if (originalEvent.touches) { |
| | | on(document, 'touchmove', this._handleFallbackAutoScroll); |
| | | } else { |
| | | on(document, 'mousemove', this._handleFallbackAutoScroll); |
| | | } |
| | | } |
| | | }, |
| | | dragOverCompleted: function dragOverCompleted(_ref2) { |
| | | var originalEvent = _ref2.originalEvent; |
| | | |
| | | // For when bubbling is canceled and using fallback (fallback 'touchmove' always reached) |
| | | if (!this.options.dragOverBubble && !originalEvent.rootEl) { |
| | | this._handleAutoScroll(originalEvent); |
| | | } |
| | | }, |
| | | drop: function drop() { |
| | | if (this.sortable.nativeDraggable) { |
| | | off(document, 'dragover', this._handleAutoScroll); |
| | | } else { |
| | | off(document, 'pointermove', this._handleFallbackAutoScroll); |
| | | off(document, 'touchmove', this._handleFallbackAutoScroll); |
| | | off(document, 'mousemove', this._handleFallbackAutoScroll); |
| | | } |
| | | |
| | | clearPointerElemChangedInterval(); |
| | | clearAutoScrolls(); |
| | | cancelThrottle(); |
| | | }, |
| | | nulling: function nulling() { |
| | | touchEvt$1 = scrollRootEl = scrollEl = scrolling = pointerElemChangedInterval = lastAutoScrollX = lastAutoScrollY = null; |
| | | autoScrolls.length = 0; |
| | | }, |
| | | _handleFallbackAutoScroll: function _handleFallbackAutoScroll(evt) { |
| | | this._handleAutoScroll(evt, true); |
| | | }, |
| | | _handleAutoScroll: function _handleAutoScroll(evt, fallback) { |
| | | var _this = this; |
| | | |
| | | var x = (evt.touches ? evt.touches[0] : evt).clientX, |
| | | y = (evt.touches ? evt.touches[0] : evt).clientY, |
| | | elem = document.elementFromPoint(x, y); |
| | | touchEvt$1 = evt; // IE does not seem to have native autoscroll, |
| | | // Edge's autoscroll seems too conditional, |
| | | // MACOS Safari does not have autoscroll, |
| | | // Firefox and Chrome are good |
| | | |
| | | if (fallback || Edge || IE11OrLess || Safari) { |
| | | autoScroll(evt, this.options, elem, fallback); // Listener for pointer element change |
| | | |
| | | var ogElemScroller = getParentAutoScrollElement(elem, true); |
| | | |
| | | if (scrolling && (!pointerElemChangedInterval || x !== lastAutoScrollX || y !== lastAutoScrollY)) { |
| | | pointerElemChangedInterval && clearPointerElemChangedInterval(); // Detect for pointer elem change, emulating native DnD behaviour |
| | | |
| | | pointerElemChangedInterval = setInterval(function () { |
| | | var newElem = getParentAutoScrollElement(document.elementFromPoint(x, y), true); |
| | | |
| | | if (newElem !== ogElemScroller) { |
| | | ogElemScroller = newElem; |
| | | clearAutoScrolls(); |
| | | } |
| | | |
| | | autoScroll(evt, _this.options, newElem, fallback); |
| | | }, 10); |
| | | lastAutoScrollX = x; |
| | | lastAutoScrollY = y; |
| | | } |
| | | } else { |
| | | // if DnD is enabled (and browser has good autoscrolling), first autoscroll will already scroll, so get parent autoscroll of first autoscroll |
| | | if (!this.options.bubbleScroll || getParentAutoScrollElement(elem, true) === getWindowScrollingElement()) { |
| | | clearAutoScrolls(); |
| | | return; |
| | | } |
| | | |
| | | autoScroll(evt, this.options, getParentAutoScrollElement(elem, false), false); |
| | | } |
| | | } |
| | | }; |
| | | return _extends(AutoScroll, { |
| | | pluginName: 'scroll', |
| | | initializeByDefault: true |
| | | }); |
| | | } |
| | | |
| | | function clearAutoScrolls() { |
| | | autoScrolls.forEach(function (autoScroll) { |
| | | clearInterval(autoScroll.pid); |
| | | }); |
| | | autoScrolls = []; |
| | | } |
| | | |
| | | function clearPointerElemChangedInterval() { |
| | | clearInterval(pointerElemChangedInterval); |
| | | } |
| | | |
| | | var autoScroll = throttle(function (evt, options, rootEl, isFallback) { |
| | | // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521 |
| | | if (!options.scroll) return; |
| | | var x = (evt.touches ? evt.touches[0] : evt).clientX, |
| | | y = (evt.touches ? evt.touches[0] : evt).clientY, |
| | | sens = options.scrollSensitivity, |
| | | speed = options.scrollSpeed, |
| | | winScroller = getWindowScrollingElement(); |
| | | var scrollThisInstance = false, |
| | | scrollCustomFn; // New scroll root, set scrollEl |
| | | |
| | | if (scrollRootEl !== rootEl) { |
| | | scrollRootEl = rootEl; |
| | | clearAutoScrolls(); |
| | | scrollEl = options.scroll; |
| | | scrollCustomFn = options.scrollFn; |
| | | |
| | | if (scrollEl === true) { |
| | | scrollEl = getParentAutoScrollElement(rootEl, true); |
| | | } |
| | | } |
| | | |
| | | var layersOut = 0; |
| | | var currentParent = scrollEl; |
| | | |
| | | do { |
| | | var el = currentParent, |
| | | rect = getRect(el), |
| | | top = rect.top, |
| | | bottom = rect.bottom, |
| | | left = rect.left, |
| | | right = rect.right, |
| | | width = rect.width, |
| | | height = rect.height, |
| | | canScrollX = void 0, |
| | | canScrollY = void 0, |
| | | scrollWidth = el.scrollWidth, |
| | | scrollHeight = el.scrollHeight, |
| | | elCSS = css(el), |
| | | scrollPosX = el.scrollLeft, |
| | | scrollPosY = el.scrollTop; |
| | | |
| | | if (el === winScroller) { |
| | | canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll' || elCSS.overflowX === 'visible'); |
| | | canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll' || elCSS.overflowY === 'visible'); |
| | | } else { |
| | | canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll'); |
| | | canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll'); |
| | | } |
| | | |
| | | var vx = canScrollX && (Math.abs(right - x) <= sens && scrollPosX + width < scrollWidth) - (Math.abs(left - x) <= sens && !!scrollPosX); |
| | | var vy = canScrollY && (Math.abs(bottom - y) <= sens && scrollPosY + height < scrollHeight) - (Math.abs(top - y) <= sens && !!scrollPosY); |
| | | |
| | | if (!autoScrolls[layersOut]) { |
| | | for (var i = 0; i <= layersOut; i++) { |
| | | if (!autoScrolls[i]) { |
| | | autoScrolls[i] = {}; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (autoScrolls[layersOut].vx != vx || autoScrolls[layersOut].vy != vy || autoScrolls[layersOut].el !== el) { |
| | | autoScrolls[layersOut].el = el; |
| | | autoScrolls[layersOut].vx = vx; |
| | | autoScrolls[layersOut].vy = vy; |
| | | clearInterval(autoScrolls[layersOut].pid); |
| | | |
| | | if (vx != 0 || vy != 0) { |
| | | scrollThisInstance = true; |
| | | /* jshint loopfunc:true */ |
| | | |
| | | autoScrolls[layersOut].pid = setInterval(function () { |
| | | // emulate drag over during autoscroll (fallback), emulating native DnD behaviour |
| | | if (isFallback && this.layer === 0) { |
| | | Sortable.active._onTouchMove(touchEvt$1); // To move ghost if it is positioned absolutely |
| | | |
| | | } |
| | | |
| | | var scrollOffsetY = autoScrolls[this.layer].vy ? autoScrolls[this.layer].vy * speed : 0; |
| | | var scrollOffsetX = autoScrolls[this.layer].vx ? autoScrolls[this.layer].vx * speed : 0; |
| | | |
| | | if (typeof scrollCustomFn === 'function') { |
| | | if (scrollCustomFn.call(Sortable.dragged.parentNode[expando], scrollOffsetX, scrollOffsetY, evt, touchEvt$1, autoScrolls[this.layer].el) !== 'continue') { |
| | | return; |
| | | } |
| | | } |
| | | |
| | | scrollBy(autoScrolls[this.layer].el, scrollOffsetX, scrollOffsetY); |
| | | }.bind({ |
| | | layer: layersOut |
| | | }), 24); |
| | | } |
| | | } |
| | | |
| | | layersOut++; |
| | | } while (options.bubbleScroll && currentParent !== winScroller && (currentParent = getParentAutoScrollElement(currentParent, false))); |
| | | |
| | | scrolling = scrollThisInstance; // in case another function catches scrolling as false in between when it is not |
| | | }, 30); |
| | | |
| | | var drop = function drop(_ref) { |
| | | var originalEvent = _ref.originalEvent, |
| | | putSortable = _ref.putSortable, |
| | | dragEl = _ref.dragEl, |
| | | activeSortable = _ref.activeSortable, |
| | | dispatchSortableEvent = _ref.dispatchSortableEvent, |
| | | hideGhostForTarget = _ref.hideGhostForTarget, |
| | | unhideGhostForTarget = _ref.unhideGhostForTarget; |
| | | if (!originalEvent) return; |
| | | var toSortable = putSortable || activeSortable; |
| | | hideGhostForTarget(); |
| | | var touch = originalEvent.changedTouches && originalEvent.changedTouches.length ? originalEvent.changedTouches[0] : originalEvent; |
| | | var target = document.elementFromPoint(touch.clientX, touch.clientY); |
| | | unhideGhostForTarget(); |
| | | |
| | | if (toSortable && !toSortable.el.contains(target)) { |
| | | dispatchSortableEvent('spill'); |
| | | this.onSpill({ |
| | | dragEl: dragEl, |
| | | putSortable: putSortable |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | function Revert() {} |
| | | |
| | | Revert.prototype = { |
| | | startIndex: null, |
| | | dragStart: function dragStart(_ref2) { |
| | | var oldDraggableIndex = _ref2.oldDraggableIndex; |
| | | this.startIndex = oldDraggableIndex; |
| | | }, |
| | | onSpill: function onSpill(_ref3) { |
| | | var dragEl = _ref3.dragEl, |
| | | putSortable = _ref3.putSortable; |
| | | this.sortable.captureAnimationState(); |
| | | |
| | | if (putSortable) { |
| | | putSortable.captureAnimationState(); |
| | | } |
| | | |
| | | var nextSibling = getChild(this.sortable.el, this.startIndex, this.options); |
| | | |
| | | if (nextSibling) { |
| | | this.sortable.el.insertBefore(dragEl, nextSibling); |
| | | } else { |
| | | this.sortable.el.appendChild(dragEl); |
| | | } |
| | | |
| | | this.sortable.animateAll(); |
| | | |
| | | if (putSortable) { |
| | | putSortable.animateAll(); |
| | | } |
| | | }, |
| | | drop: drop |
| | | }; |
| | | |
| | | _extends(Revert, { |
| | | pluginName: 'revertOnSpill' |
| | | }); |
| | | |
| | | function Remove() {} |
| | | |
| | | Remove.prototype = { |
| | | onSpill: function onSpill(_ref4) { |
| | | var dragEl = _ref4.dragEl, |
| | | putSortable = _ref4.putSortable; |
| | | var parentSortable = putSortable || this.sortable; |
| | | parentSortable.captureAnimationState(); |
| | | dragEl.parentNode && dragEl.parentNode.removeChild(dragEl); |
| | | parentSortable.animateAll(); |
| | | }, |
| | | drop: drop |
| | | }; |
| | | |
| | | _extends(Remove, { |
| | | pluginName: 'removeOnSpill' |
| | | }); |
| | | |
| | | var lastSwapEl; |
| | | |
| | | function SwapPlugin() { |
| | | function Swap() { |
| | | this.defaults = { |
| | | swapClass: 'sortable-swap-highlight' |
| | | }; |
| | | } |
| | | |
| | | Swap.prototype = { |
| | | dragStart: function dragStart(_ref) { |
| | | var dragEl = _ref.dragEl; |
| | | lastSwapEl = dragEl; |
| | | }, |
| | | dragOverValid: function dragOverValid(_ref2) { |
| | | var completed = _ref2.completed, |
| | | target = _ref2.target, |
| | | onMove = _ref2.onMove, |
| | | activeSortable = _ref2.activeSortable, |
| | | changed = _ref2.changed, |
| | | cancel = _ref2.cancel; |
| | | if (!activeSortable.options.swap) return; |
| | | var el = this.sortable.el, |
| | | options = this.options; |
| | | |
| | | if (target && target !== el) { |
| | | var prevSwapEl = lastSwapEl; |
| | | |
| | | if (onMove(target) !== false) { |
| | | toggleClass(target, options.swapClass, true); |
| | | lastSwapEl = target; |
| | | } else { |
| | | lastSwapEl = null; |
| | | } |
| | | |
| | | if (prevSwapEl && prevSwapEl !== lastSwapEl) { |
| | | toggleClass(prevSwapEl, options.swapClass, false); |
| | | } |
| | | } |
| | | |
| | | changed(); |
| | | completed(true); |
| | | cancel(); |
| | | }, |
| | | drop: function drop(_ref3) { |
| | | var activeSortable = _ref3.activeSortable, |
| | | putSortable = _ref3.putSortable, |
| | | dragEl = _ref3.dragEl; |
| | | var toSortable = putSortable || this.sortable; |
| | | var options = this.options; |
| | | lastSwapEl && toggleClass(lastSwapEl, options.swapClass, false); |
| | | |
| | | if (lastSwapEl && (options.swap || putSortable && putSortable.options.swap)) { |
| | | if (dragEl !== lastSwapEl) { |
| | | toSortable.captureAnimationState(); |
| | | if (toSortable !== activeSortable) activeSortable.captureAnimationState(); |
| | | swapNodes(dragEl, lastSwapEl); |
| | | toSortable.animateAll(); |
| | | if (toSortable !== activeSortable) activeSortable.animateAll(); |
| | | } |
| | | } |
| | | }, |
| | | nulling: function nulling() { |
| | | lastSwapEl = null; |
| | | } |
| | | }; |
| | | return _extends(Swap, { |
| | | pluginName: 'swap', |
| | | eventProperties: function eventProperties() { |
| | | return { |
| | | swapItem: lastSwapEl |
| | | }; |
| | | } |
| | | }); |
| | | } |
| | | |
| | | function swapNodes(n1, n2) { |
| | | var p1 = n1.parentNode, |
| | | p2 = n2.parentNode, |
| | | i1, |
| | | i2; |
| | | if (!p1 || !p2 || p1.isEqualNode(n2) || p2.isEqualNode(n1)) return; |
| | | i1 = index(n1); |
| | | i2 = index(n2); |
| | | |
| | | if (p1.isEqualNode(p2) && i1 < i2) { |
| | | i2++; |
| | | } |
| | | |
| | | p1.insertBefore(n2, p1.children[i1]); |
| | | p2.insertBefore(n1, p2.children[i2]); |
| | | } |
| | | |
| | | var multiDragElements = [], |
| | | multiDragClones = [], |
| | | lastMultiDragSelect, |
| | | // for selection with modifier key down (SHIFT) |
| | | multiDragSortable, |
| | | initialFolding = false, |
| | | // Initial multi-drag fold when drag started |
| | | folding = false, |
| | | // Folding any other time |
| | | dragStarted = false, |
| | | dragEl$1, |
| | | clonesFromRect, |
| | | clonesHidden; |
| | | |
| | | function MultiDragPlugin() { |
| | | function MultiDrag(sortable) { |
| | | // Bind all private methods |
| | | for (var fn in this) { |
| | | if (fn.charAt(0) === '_' && typeof this[fn] === 'function') { |
| | | this[fn] = this[fn].bind(this); |
| | | } |
| | | } |
| | | |
| | | if (sortable.options.supportPointer) { |
| | | on(document, 'pointerup', this._deselectMultiDrag); |
| | | } else { |
| | | on(document, 'mouseup', this._deselectMultiDrag); |
| | | on(document, 'touchend', this._deselectMultiDrag); |
| | | } |
| | | |
| | | on(document, 'keydown', this._checkKeyDown); |
| | | on(document, 'keyup', this._checkKeyUp); |
| | | this.defaults = { |
| | | selectedClass: 'sortable-selected', |
| | | multiDragKey: null, |
| | | setData: function setData(dataTransfer, dragEl) { |
| | | var data = ''; |
| | | |
| | | if (multiDragElements.length && multiDragSortable === sortable) { |
| | | multiDragElements.forEach(function (multiDragElement, i) { |
| | | data += (!i ? '' : ', ') + multiDragElement.textContent; |
| | | }); |
| | | } else { |
| | | data = dragEl.textContent; |
| | | } |
| | | |
| | | dataTransfer.setData('Text', data); |
| | | } |
| | | }; |
| | | } |
| | | |
| | | MultiDrag.prototype = { |
| | | multiDragKeyDown: false, |
| | | isMultiDrag: false, |
| | | delayStartGlobal: function delayStartGlobal(_ref) { |
| | | var dragged = _ref.dragEl; |
| | | dragEl$1 = dragged; |
| | | }, |
| | | delayEnded: function delayEnded() { |
| | | this.isMultiDrag = ~multiDragElements.indexOf(dragEl$1); |
| | | }, |
| | | setupClone: function setupClone(_ref2) { |
| | | var sortable = _ref2.sortable, |
| | | cancel = _ref2.cancel; |
| | | if (!this.isMultiDrag) return; |
| | | |
| | | for (var i = 0; i < multiDragElements.length; i++) { |
| | | multiDragClones.push(clone(multiDragElements[i])); |
| | | multiDragClones[i].sortableIndex = multiDragElements[i].sortableIndex; |
| | | multiDragClones[i].draggable = false; |
| | | multiDragClones[i].style['will-change'] = ''; |
| | | toggleClass(multiDragClones[i], this.options.selectedClass, false); |
| | | multiDragElements[i] === dragEl$1 && toggleClass(multiDragClones[i], this.options.chosenClass, false); |
| | | } |
| | | |
| | | sortable._hideClone(); |
| | | |
| | | cancel(); |
| | | }, |
| | | clone: function clone(_ref3) { |
| | | var sortable = _ref3.sortable, |
| | | rootEl = _ref3.rootEl, |
| | | dispatchSortableEvent = _ref3.dispatchSortableEvent, |
| | | cancel = _ref3.cancel; |
| | | if (!this.isMultiDrag) return; |
| | | |
| | | if (!this.options.removeCloneOnHide) { |
| | | if (multiDragElements.length && multiDragSortable === sortable) { |
| | | insertMultiDragClones(true, rootEl); |
| | | dispatchSortableEvent('clone'); |
| | | cancel(); |
| | | } |
| | | } |
| | | }, |
| | | showClone: function showClone(_ref4) { |
| | | var cloneNowShown = _ref4.cloneNowShown, |
| | | rootEl = _ref4.rootEl, |
| | | cancel = _ref4.cancel; |
| | | if (!this.isMultiDrag) return; |
| | | insertMultiDragClones(false, rootEl); |
| | | multiDragClones.forEach(function (clone) { |
| | | css(clone, 'display', ''); |
| | | }); |
| | | cloneNowShown(); |
| | | clonesHidden = false; |
| | | cancel(); |
| | | }, |
| | | hideClone: function hideClone(_ref5) { |
| | | var _this = this; |
| | | |
| | | var sortable = _ref5.sortable, |
| | | cloneNowHidden = _ref5.cloneNowHidden, |
| | | cancel = _ref5.cancel; |
| | | if (!this.isMultiDrag) return; |
| | | multiDragClones.forEach(function (clone) { |
| | | css(clone, 'display', 'none'); |
| | | |
| | | if (_this.options.removeCloneOnHide && clone.parentNode) { |
| | | clone.parentNode.removeChild(clone); |
| | | } |
| | | }); |
| | | cloneNowHidden(); |
| | | clonesHidden = true; |
| | | cancel(); |
| | | }, |
| | | dragStartGlobal: function dragStartGlobal(_ref6) { |
| | | var sortable = _ref6.sortable; |
| | | |
| | | if (!this.isMultiDrag && multiDragSortable) { |
| | | multiDragSortable.multiDrag._deselectMultiDrag(); |
| | | } |
| | | |
| | | multiDragElements.forEach(function (multiDragElement) { |
| | | multiDragElement.sortableIndex = index(multiDragElement); |
| | | }); // Sort multi-drag elements |
| | | |
| | | multiDragElements = multiDragElements.sort(function (a, b) { |
| | | return a.sortableIndex - b.sortableIndex; |
| | | }); |
| | | dragStarted = true; |
| | | }, |
| | | dragStarted: function dragStarted(_ref7) { |
| | | var _this2 = this; |
| | | |
| | | var sortable = _ref7.sortable; |
| | | if (!this.isMultiDrag) return; |
| | | |
| | | if (this.options.sort) { |
| | | // Capture rects, |
| | | // hide multi drag elements (by positioning them absolute), |
| | | // set multi drag elements rects to dragRect, |
| | | // show multi drag elements, |
| | | // animate to rects, |
| | | // unset rects & remove from DOM |
| | | sortable.captureAnimationState(); |
| | | |
| | | if (this.options.animation) { |
| | | multiDragElements.forEach(function (multiDragElement) { |
| | | if (multiDragElement === dragEl$1) return; |
| | | css(multiDragElement, 'position', 'absolute'); |
| | | }); |
| | | var dragRect = getRect(dragEl$1, false, true, true); |
| | | multiDragElements.forEach(function (multiDragElement) { |
| | | if (multiDragElement === dragEl$1) return; |
| | | setRect(multiDragElement, dragRect); |
| | | }); |
| | | folding = true; |
| | | initialFolding = true; |
| | | } |
| | | } |
| | | |
| | | sortable.animateAll(function () { |
| | | folding = false; |
| | | initialFolding = false; |
| | | |
| | | if (_this2.options.animation) { |
| | | multiDragElements.forEach(function (multiDragElement) { |
| | | unsetRect(multiDragElement); |
| | | }); |
| | | } // Remove all auxiliary multidrag items from el, if sorting enabled |
| | | |
| | | |
| | | if (_this2.options.sort) { |
| | | removeMultiDragElements(); |
| | | } |
| | | }); |
| | | }, |
| | | dragOver: function dragOver(_ref8) { |
| | | var target = _ref8.target, |
| | | completed = _ref8.completed, |
| | | cancel = _ref8.cancel; |
| | | |
| | | if (folding && ~multiDragElements.indexOf(target)) { |
| | | completed(false); |
| | | cancel(); |
| | | } |
| | | }, |
| | | revert: function revert(_ref9) { |
| | | var fromSortable = _ref9.fromSortable, |
| | | rootEl = _ref9.rootEl, |
| | | sortable = _ref9.sortable, |
| | | dragRect = _ref9.dragRect; |
| | | |
| | | if (multiDragElements.length > 1) { |
| | | // Setup unfold animation |
| | | multiDragElements.forEach(function (multiDragElement) { |
| | | sortable.addAnimationState({ |
| | | target: multiDragElement, |
| | | rect: folding ? getRect(multiDragElement) : dragRect |
| | | }); |
| | | unsetRect(multiDragElement); |
| | | multiDragElement.fromRect = dragRect; |
| | | fromSortable.removeAnimationState(multiDragElement); |
| | | }); |
| | | folding = false; |
| | | insertMultiDragElements(!this.options.removeCloneOnHide, rootEl); |
| | | } |
| | | }, |
| | | dragOverCompleted: function dragOverCompleted(_ref10) { |
| | | var sortable = _ref10.sortable, |
| | | isOwner = _ref10.isOwner, |
| | | insertion = _ref10.insertion, |
| | | activeSortable = _ref10.activeSortable, |
| | | parentEl = _ref10.parentEl, |
| | | putSortable = _ref10.putSortable; |
| | | var options = this.options; |
| | | |
| | | if (insertion) { |
| | | // Clones must be hidden before folding animation to capture dragRectAbsolute properly |
| | | if (isOwner) { |
| | | activeSortable._hideClone(); |
| | | } |
| | | |
| | | initialFolding = false; // If leaving sort:false root, or already folding - Fold to new location |
| | | |
| | | if (options.animation && multiDragElements.length > 1 && (folding || !isOwner && !activeSortable.options.sort && !putSortable)) { |
| | | // Fold: Set all multi drag elements's rects to dragEl's rect when multi-drag elements are invisible |
| | | var dragRectAbsolute = getRect(dragEl$1, false, true, true); |
| | | multiDragElements.forEach(function (multiDragElement) { |
| | | if (multiDragElement === dragEl$1) return; |
| | | setRect(multiDragElement, dragRectAbsolute); // Move element(s) to end of parentEl so that it does not interfere with multi-drag clones insertion if they are inserted |
| | | // while folding, and so that we can capture them again because old sortable will no longer be fromSortable |
| | | |
| | | parentEl.appendChild(multiDragElement); |
| | | }); |
| | | folding = true; |
| | | } // Clones must be shown (and check to remove multi drags) after folding when interfering multiDragElements are moved out |
| | | |
| | | |
| | | if (!isOwner) { |
| | | // Only remove if not folding (folding will remove them anyways) |
| | | if (!folding) { |
| | | removeMultiDragElements(); |
| | | } |
| | | |
| | | if (multiDragElements.length > 1) { |
| | | var clonesHiddenBefore = clonesHidden; |
| | | |
| | | activeSortable._showClone(sortable); // Unfold animation for clones if showing from hidden |
| | | |
| | | |
| | | if (activeSortable.options.animation && !clonesHidden && clonesHiddenBefore) { |
| | | multiDragClones.forEach(function (clone) { |
| | | activeSortable.addAnimationState({ |
| | | target: clone, |
| | | rect: clonesFromRect |
| | | }); |
| | | clone.fromRect = clonesFromRect; |
| | | clone.thisAnimationDuration = null; |
| | | }); |
| | | } |
| | | } else { |
| | | activeSortable._showClone(sortable); |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | dragOverAnimationCapture: function dragOverAnimationCapture(_ref11) { |
| | | var dragRect = _ref11.dragRect, |
| | | isOwner = _ref11.isOwner, |
| | | activeSortable = _ref11.activeSortable; |
| | | multiDragElements.forEach(function (multiDragElement) { |
| | | multiDragElement.thisAnimationDuration = null; |
| | | }); |
| | | |
| | | if (activeSortable.options.animation && !isOwner && activeSortable.multiDrag.isMultiDrag) { |
| | | clonesFromRect = _extends({}, dragRect); |
| | | var dragMatrix = matrix(dragEl$1, true); |
| | | clonesFromRect.top -= dragMatrix.f; |
| | | clonesFromRect.left -= dragMatrix.e; |
| | | } |
| | | }, |
| | | dragOverAnimationComplete: function dragOverAnimationComplete() { |
| | | if (folding) { |
| | | folding = false; |
| | | removeMultiDragElements(); |
| | | } |
| | | }, |
| | | drop: function drop(_ref12) { |
| | | var evt = _ref12.originalEvent, |
| | | rootEl = _ref12.rootEl, |
| | | parentEl = _ref12.parentEl, |
| | | sortable = _ref12.sortable, |
| | | dispatchSortableEvent = _ref12.dispatchSortableEvent, |
| | | oldIndex = _ref12.oldIndex, |
| | | putSortable = _ref12.putSortable; |
| | | var toSortable = putSortable || this.sortable; |
| | | if (!evt) return; |
| | | var options = this.options, |
| | | children = parentEl.children; // Multi-drag selection |
| | | |
| | | if (!dragStarted) { |
| | | if (options.multiDragKey && !this.multiDragKeyDown) { |
| | | this._deselectMultiDrag(); |
| | | } |
| | | |
| | | toggleClass(dragEl$1, options.selectedClass, !~multiDragElements.indexOf(dragEl$1)); |
| | | |
| | | if (!~multiDragElements.indexOf(dragEl$1)) { |
| | | multiDragElements.push(dragEl$1); |
| | | dispatchEvent({ |
| | | sortable: sortable, |
| | | rootEl: rootEl, |
| | | name: 'select', |
| | | targetEl: dragEl$1, |
| | | originalEvt: evt |
| | | }); // Modifier activated, select from last to dragEl |
| | | |
| | | if (evt.shiftKey && lastMultiDragSelect && sortable.el.contains(lastMultiDragSelect)) { |
| | | var lastIndex = index(lastMultiDragSelect), |
| | | currentIndex = index(dragEl$1); |
| | | |
| | | if (~lastIndex && ~currentIndex && lastIndex !== currentIndex) { |
| | | // Must include lastMultiDragSelect (select it), in case modified selection from no selection |
| | | // (but previous selection existed) |
| | | var n, i; |
| | | |
| | | if (currentIndex > lastIndex) { |
| | | i = lastIndex; |
| | | n = currentIndex; |
| | | } else { |
| | | i = currentIndex; |
| | | n = lastIndex + 1; |
| | | } |
| | | |
| | | for (; i < n; i++) { |
| | | if (~multiDragElements.indexOf(children[i])) continue; |
| | | toggleClass(children[i], options.selectedClass, true); |
| | | multiDragElements.push(children[i]); |
| | | dispatchEvent({ |
| | | sortable: sortable, |
| | | rootEl: rootEl, |
| | | name: 'select', |
| | | targetEl: children[i], |
| | | originalEvt: evt |
| | | }); |
| | | } |
| | | } |
| | | } else { |
| | | lastMultiDragSelect = dragEl$1; |
| | | } |
| | | |
| | | multiDragSortable = toSortable; |
| | | } else { |
| | | multiDragElements.splice(multiDragElements.indexOf(dragEl$1), 1); |
| | | lastMultiDragSelect = null; |
| | | dispatchEvent({ |
| | | sortable: sortable, |
| | | rootEl: rootEl, |
| | | name: 'deselect', |
| | | targetEl: dragEl$1, |
| | | originalEvt: evt |
| | | }); |
| | | } |
| | | } // Multi-drag drop |
| | | |
| | | |
| | | if (dragStarted && this.isMultiDrag) { |
| | | // Do not "unfold" after around dragEl if reverted |
| | | if ((parentEl[expando].options.sort || parentEl !== rootEl) && multiDragElements.length > 1) { |
| | | var dragRect = getRect(dragEl$1), |
| | | multiDragIndex = index(dragEl$1, ':not(.' + this.options.selectedClass + ')'); |
| | | if (!initialFolding && options.animation) dragEl$1.thisAnimationDuration = null; |
| | | toSortable.captureAnimationState(); |
| | | |
| | | if (!initialFolding) { |
| | | if (options.animation) { |
| | | dragEl$1.fromRect = dragRect; |
| | | multiDragElements.forEach(function (multiDragElement) { |
| | | multiDragElement.thisAnimationDuration = null; |
| | | |
| | | if (multiDragElement !== dragEl$1) { |
| | | var rect = folding ? getRect(multiDragElement) : dragRect; |
| | | multiDragElement.fromRect = rect; // Prepare unfold animation |
| | | |
| | | toSortable.addAnimationState({ |
| | | target: multiDragElement, |
| | | rect: rect |
| | | }); |
| | | } |
| | | }); |
| | | } // Multi drag elements are not necessarily removed from the DOM on drop, so to reinsert |
| | | // properly they must all be removed |
| | | |
| | | |
| | | removeMultiDragElements(); |
| | | multiDragElements.forEach(function (multiDragElement) { |
| | | if (children[multiDragIndex]) { |
| | | parentEl.insertBefore(multiDragElement, children[multiDragIndex]); |
| | | } else { |
| | | parentEl.appendChild(multiDragElement); |
| | | } |
| | | |
| | | multiDragIndex++; |
| | | }); // If initial folding is done, the elements may have changed position because they are now |
| | | // unfolding around dragEl, even though dragEl may not have his index changed, so update event |
| | | // must be fired here as Sortable will not. |
| | | |
| | | if (oldIndex === index(dragEl$1)) { |
| | | var update = false; |
| | | multiDragElements.forEach(function (multiDragElement) { |
| | | if (multiDragElement.sortableIndex !== index(multiDragElement)) { |
| | | update = true; |
| | | return; |
| | | } |
| | | }); |
| | | |
| | | if (update) { |
| | | dispatchSortableEvent('update'); |
| | | } |
| | | } |
| | | } // Must be done after capturing individual rects (scroll bar) |
| | | |
| | | |
| | | multiDragElements.forEach(function (multiDragElement) { |
| | | unsetRect(multiDragElement); |
| | | }); |
| | | toSortable.animateAll(); |
| | | } |
| | | |
| | | multiDragSortable = toSortable; |
| | | } // Remove clones if necessary |
| | | |
| | | |
| | | if (rootEl === parentEl || putSortable && putSortable.lastPutMode !== 'clone') { |
| | | multiDragClones.forEach(function (clone) { |
| | | clone.parentNode && clone.parentNode.removeChild(clone); |
| | | }); |
| | | } |
| | | }, |
| | | nullingGlobal: function nullingGlobal() { |
| | | this.isMultiDrag = dragStarted = false; |
| | | multiDragClones.length = 0; |
| | | }, |
| | | destroyGlobal: function destroyGlobal() { |
| | | this._deselectMultiDrag(); |
| | | |
| | | off(document, 'pointerup', this._deselectMultiDrag); |
| | | off(document, 'mouseup', this._deselectMultiDrag); |
| | | off(document, 'touchend', this._deselectMultiDrag); |
| | | off(document, 'keydown', this._checkKeyDown); |
| | | off(document, 'keyup', this._checkKeyUp); |
| | | }, |
| | | _deselectMultiDrag: function _deselectMultiDrag(evt) { |
| | | if (typeof dragStarted !== "undefined" && dragStarted) return; // Only deselect if selection is in this sortable |
| | | |
| | | if (multiDragSortable !== this.sortable) return; // Only deselect if target is not item in this sortable |
| | | |
| | | if (evt && closest(evt.target, this.options.draggable, this.sortable.el, false)) return; // Only deselect if left click |
| | | |
| | | if (evt && evt.button !== 0) return; |
| | | |
| | | while (multiDragElements.length) { |
| | | var el = multiDragElements[0]; |
| | | toggleClass(el, this.options.selectedClass, false); |
| | | multiDragElements.shift(); |
| | | dispatchEvent({ |
| | | sortable: this.sortable, |
| | | rootEl: this.sortable.el, |
| | | name: 'deselect', |
| | | targetEl: el, |
| | | originalEvt: evt |
| | | }); |
| | | } |
| | | }, |
| | | _checkKeyDown: function _checkKeyDown(evt) { |
| | | if (evt.key === this.options.multiDragKey) { |
| | | this.multiDragKeyDown = true; |
| | | } |
| | | }, |
| | | _checkKeyUp: function _checkKeyUp(evt) { |
| | | if (evt.key === this.options.multiDragKey) { |
| | | this.multiDragKeyDown = false; |
| | | } |
| | | } |
| | | }; |
| | | return _extends(MultiDrag, { |
| | | // Static methods & properties |
| | | pluginName: 'multiDrag', |
| | | utils: { |
| | | /** |
| | | * Selects the provided multi-drag item |
| | | * @param {HTMLElement} el The element to be selected |
| | | */ |
| | | select: function select(el) { |
| | | var sortable = el.parentNode[expando]; |
| | | if (!sortable || !sortable.options.multiDrag || ~multiDragElements.indexOf(el)) return; |
| | | |
| | | if (multiDragSortable && multiDragSortable !== sortable) { |
| | | multiDragSortable.multiDrag._deselectMultiDrag(); |
| | | |
| | | multiDragSortable = sortable; |
| | | } |
| | | |
| | | toggleClass(el, sortable.options.selectedClass, true); |
| | | multiDragElements.push(el); |
| | | }, |
| | | |
| | | /** |
| | | * Deselects the provided multi-drag item |
| | | * @param {HTMLElement} el The element to be deselected |
| | | */ |
| | | deselect: function deselect(el) { |
| | | var sortable = el.parentNode[expando], |
| | | index = multiDragElements.indexOf(el); |
| | | if (!sortable || !sortable.options.multiDrag || !~index) return; |
| | | toggleClass(el, sortable.options.selectedClass, false); |
| | | multiDragElements.splice(index, 1); |
| | | } |
| | | }, |
| | | eventProperties: function eventProperties() { |
| | | var _this3 = this; |
| | | |
| | | var oldIndicies = [], |
| | | newIndicies = []; |
| | | multiDragElements.forEach(function (multiDragElement) { |
| | | oldIndicies.push({ |
| | | multiDragElement: multiDragElement, |
| | | index: multiDragElement.sortableIndex |
| | | }); // multiDragElements will already be sorted if folding |
| | | |
| | | var newIndex; |
| | | |
| | | if (folding && multiDragElement !== dragEl$1) { |
| | | newIndex = -1; |
| | | } else if (folding) { |
| | | newIndex = index(multiDragElement, ':not(.' + _this3.options.selectedClass + ')'); |
| | | } else { |
| | | newIndex = index(multiDragElement); |
| | | } |
| | | |
| | | newIndicies.push({ |
| | | multiDragElement: multiDragElement, |
| | | index: newIndex |
| | | }); |
| | | }); |
| | | return { |
| | | items: _toConsumableArray(multiDragElements), |
| | | clones: [].concat(multiDragClones), |
| | | oldIndicies: oldIndicies, |
| | | newIndicies: newIndicies |
| | | }; |
| | | }, |
| | | optionListeners: { |
| | | multiDragKey: function multiDragKey(key) { |
| | | key = key.toLowerCase(); |
| | | |
| | | if (key === 'ctrl') { |
| | | key = 'Control'; |
| | | } else if (key.length > 1) { |
| | | key = key.charAt(0).toUpperCase() + key.substr(1); |
| | | } |
| | | |
| | | return key; |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | function insertMultiDragElements(clonesInserted, rootEl) { |
| | | multiDragElements.forEach(function (multiDragElement, i) { |
| | | var target = rootEl.children[multiDragElement.sortableIndex + (clonesInserted ? Number(i) : 0)]; |
| | | |
| | | if (target) { |
| | | rootEl.insertBefore(multiDragElement, target); |
| | | } else { |
| | | rootEl.appendChild(multiDragElement); |
| | | } |
| | | }); |
| | | } |
| | | /** |
| | | * Insert multi-drag clones |
| | | * @param {[Boolean]} elementsInserted Whether the multi-drag elements are inserted |
| | | * @param {HTMLElement} rootEl |
| | | */ |
| | | |
| | | |
| | | function insertMultiDragClones(elementsInserted, rootEl) { |
| | | multiDragClones.forEach(function (clone, i) { |
| | | var target = rootEl.children[clone.sortableIndex + (elementsInserted ? Number(i) : 0)]; |
| | | |
| | | if (target) { |
| | | rootEl.insertBefore(clone, target); |
| | | } else { |
| | | rootEl.appendChild(clone); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | function removeMultiDragElements() { |
| | | multiDragElements.forEach(function (multiDragElement) { |
| | | if (multiDragElement === dragEl$1) return; |
| | | multiDragElement.parentNode && multiDragElement.parentNode.removeChild(multiDragElement); |
| | | }); |
| | | } |
| | | |
| | | Sortable.mount(new AutoScrollPlugin()); |
| | | Sortable.mount(Remove, Revert); |
| | | |
| | | Sortable.mount(new SwapPlugin()); |
| | | Sortable.mount(new MultiDragPlugin()); |
| | | |
| | | return Sortable; |
| | | |
| | | })); |
New file |
| | |
| | | /*! Sortable 1.10.2 - MIT | git://github.com/SortableJS/Sortable.git */ |
| | | !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).Sortable=e()}(this,function(){"use strict";function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function a(){return(a=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(t[o]=n[o])}return t}).apply(this,arguments)}function I(i){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{},e=Object.keys(r);"function"==typeof Object.getOwnPropertySymbols&&(e=e.concat(Object.getOwnPropertySymbols(r).filter(function(t){return Object.getOwnPropertyDescriptor(r,t).enumerable}))),e.forEach(function(t){var e,n,o;e=i,o=r[n=t],n in e?Object.defineProperty(e,n,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[n]=o})}return i}function l(t,e){if(null==t)return{};var n,o,i=function(t,e){if(null==t)return{};var n,o,i={},r=Object.keys(t);for(o=0;o<r.length;o++)n=r[o],0<=e.indexOf(n)||(i[n]=t[n]);return i}(t,e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);for(o=0;o<r.length;o++)n=r[o],0<=e.indexOf(n)||Object.prototype.propertyIsEnumerable.call(t,n)&&(i[n]=t[n])}return i}function e(t){return function(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e<t.length;e++)n[e]=t[e];return n}}(t)||function(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}()}function t(t){if("undefined"!=typeof window&&window.navigator)return!!navigator.userAgent.match(t)}var w=t(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i),E=t(/Edge/i),c=t(/firefox/i),s=t(/safari/i)&&!t(/chrome/i)&&!t(/android/i),n=t(/iP(ad|od|hone)/i),i=t(/chrome/i)&&t(/android/i),r={capture:!1,passive:!1};function u(t,e,n){t.addEventListener(e,n,!w&&r)}function d(t,e,n){t.removeEventListener(e,n,!w&&r)}function h(t,e){if(e){if(">"===e[0]&&(e=e.substring(1)),t)try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(t){return!1}return!1}}function P(t,e,n,o){if(t){n=n||document;do{if(null!=e&&(">"===e[0]?t.parentNode===n&&h(t,e):h(t,e))||o&&t===n)return t;if(t===n)break}while(t=(i=t).host&&i!==document&&i.host.nodeType?i.host:i.parentNode)}var i;return null}var f,p=/\s+/g;function k(t,e,n){if(t&&e)if(t.classList)t.classList[n?"add":"remove"](e);else{var o=(" "+t.className+" ").replace(p," ").replace(" "+e+" "," ");t.className=(o+(n?" "+e:"")).replace(p," ")}}function R(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];e in o||-1!==e.indexOf("webkit")||(e="-webkit-"+e),o[e]=n+("string"==typeof n?"":"px")}}function v(t,e){var n="";if("string"==typeof t)n=t;else do{var o=R(t,"transform");o&&"none"!==o&&(n=o+" "+n)}while(!e&&(t=t.parentNode));var i=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return i&&new i(n)}function g(t,e,n){if(t){var o=t.getElementsByTagName(e),i=0,r=o.length;if(n)for(;i<r;i++)n(o[i],i);return o}return[]}function N(){var t=document.scrollingElement;return t||document.documentElement}function X(t,e,n,o,i){if(t.getBoundingClientRect||t===window){var r,a,l,s,c,u,d;if(d=t!==window&&t!==N()?(a=(r=t.getBoundingClientRect()).top,l=r.left,s=r.bottom,c=r.right,u=r.height,r.width):(l=a=0,s=window.innerHeight,c=window.innerWidth,u=window.innerHeight,window.innerWidth),(e||n)&&t!==window&&(i=i||t.parentNode,!w))do{if(i&&i.getBoundingClientRect&&("none"!==R(i,"transform")||n&&"static"!==R(i,"position"))){var h=i.getBoundingClientRect();a-=h.top+parseInt(R(i,"border-top-width")),l-=h.left+parseInt(R(i,"border-left-width")),s=a+r.height,c=l+r.width;break}}while(i=i.parentNode);if(o&&t!==window){var f=v(i||t),p=f&&f.a,g=f&&f.d;f&&(s=(a/=g)+(u/=g),c=(l/=p)+(d/=p))}return{top:a,left:l,bottom:s,right:c,width:d,height:u}}}function Y(t,e,n){for(var o=H(t,!0),i=X(t)[e];o;){var r=X(o)[n];if(!("top"===n||"left"===n?r<=i:i<=r))return o;if(o===N())break;o=H(o,!1)}return!1}function m(t,e,n){for(var o=0,i=0,r=t.children;i<r.length;){if("none"!==r[i].style.display&&r[i]!==Rt.ghost&&r[i]!==Rt.dragged&&P(r[i],n.draggable,t,!1)){if(o===e)return r[i];o++}i++}return null}function B(t,e){for(var n=t.lastElementChild;n&&(n===Rt.ghost||"none"===R(n,"display")||e&&!h(n,e));)n=n.previousElementSibling;return n||null}function F(t,e){var n=0;if(!t||!t.parentNode)return-1;for(;t=t.previousElementSibling;)"TEMPLATE"===t.nodeName.toUpperCase()||t===Rt.clone||e&&!h(t,e)||n++;return n}function b(t){var e=0,n=0,o=N();if(t)do{var i=v(t),r=i.a,a=i.d;e+=t.scrollLeft*r,n+=t.scrollTop*a}while(t!==o&&(t=t.parentNode));return[e,n]}function H(t,e){if(!t||!t.getBoundingClientRect)return N();var n=t,o=!1;do{if(n.clientWidth<n.scrollWidth||n.clientHeight<n.scrollHeight){var i=R(n);if(n.clientWidth<n.scrollWidth&&("auto"==i.overflowX||"scroll"==i.overflowX)||n.clientHeight<n.scrollHeight&&("auto"==i.overflowY||"scroll"==i.overflowY)){if(!n.getBoundingClientRect||n===document.body)return N();if(o||e)return n;o=!0}}}while(n=n.parentNode);return N()}function y(t,e){return Math.round(t.top)===Math.round(e.top)&&Math.round(t.left)===Math.round(e.left)&&Math.round(t.height)===Math.round(e.height)&&Math.round(t.width)===Math.round(e.width)}function D(e,n){return function(){if(!f){var t=arguments;1===t.length?e.call(this,t[0]):e.apply(this,t),f=setTimeout(function(){f=void 0},n)}}}function L(t,e,n){t.scrollLeft+=e,t.scrollTop+=n}function S(t){var e=window.Polymer,n=window.jQuery||window.Zepto;return e&&e.dom?e.dom(t).cloneNode(!0):n?n(t).clone(!0)[0]:t.cloneNode(!0)}function _(t,e){R(t,"position","absolute"),R(t,"top",e.top),R(t,"left",e.left),R(t,"width",e.width),R(t,"height",e.height)}function C(t){R(t,"position",""),R(t,"top",""),R(t,"left",""),R(t,"width",""),R(t,"height","")}var j="Sortable"+(new Date).getTime();function T(){var e,o=[];return{captureAnimationState:function(){o=[],this.options.animation&&[].slice.call(this.el.children).forEach(function(t){if("none"!==R(t,"display")&&t!==Rt.ghost){o.push({target:t,rect:X(t)});var e=I({},o[o.length-1].rect);if(t.thisAnimationDuration){var n=v(t,!0);n&&(e.top-=n.f,e.left-=n.e)}t.fromRect=e}})},addAnimationState:function(t){o.push(t)},removeAnimationState:function(t){o.splice(function(t,e){for(var n in t)if(t.hasOwnProperty(n))for(var o in e)if(e.hasOwnProperty(o)&&e[o]===t[n][o])return Number(n);return-1}(o,{target:t}),1)},animateAll:function(t){var c=this;if(!this.options.animation)return clearTimeout(e),void("function"==typeof t&&t());var u=!1,d=0;o.forEach(function(t){var e=0,n=t.target,o=n.fromRect,i=X(n),r=n.prevFromRect,a=n.prevToRect,l=t.rect,s=v(n,!0);s&&(i.top-=s.f,i.left-=s.e),n.toRect=i,n.thisAnimationDuration&&y(r,i)&&!y(o,i)&&(l.top-i.top)/(l.left-i.left)==(o.top-i.top)/(o.left-i.left)&&(e=function(t,e,n,o){return Math.sqrt(Math.pow(e.top-t.top,2)+Math.pow(e.left-t.left,2))/Math.sqrt(Math.pow(e.top-n.top,2)+Math.pow(e.left-n.left,2))*o.animation}(l,r,a,c.options)),y(i,o)||(n.prevFromRect=o,n.prevToRect=i,e||(e=c.options.animation),c.animate(n,l,i,e)),e&&(u=!0,d=Math.max(d,e),clearTimeout(n.animationResetTimer),n.animationResetTimer=setTimeout(function(){n.animationTime=0,n.prevFromRect=null,n.fromRect=null,n.prevToRect=null,n.thisAnimationDuration=null},e),n.thisAnimationDuration=e)}),clearTimeout(e),u?e=setTimeout(function(){"function"==typeof t&&t()},d):"function"==typeof t&&t(),o=[]},animate:function(t,e,n,o){if(o){R(t,"transition",""),R(t,"transform","");var i=v(this.el),r=i&&i.a,a=i&&i.d,l=(e.left-n.left)/(r||1),s=(e.top-n.top)/(a||1);t.animatingX=!!l,t.animatingY=!!s,R(t,"transform","translate3d("+l+"px,"+s+"px,0)"),function(t){t.offsetWidth}(t),R(t,"transition","transform "+o+"ms"+(this.options.easing?" "+this.options.easing:"")),R(t,"transform","translate3d(0,0,0)"),"number"==typeof t.animated&&clearTimeout(t.animated),t.animated=setTimeout(function(){R(t,"transition",""),R(t,"transform",""),t.animated=!1,t.animatingX=!1,t.animatingY=!1},o)}}}}var x=[],M={initializeByDefault:!0},O={mount:function(t){for(var e in M)!M.hasOwnProperty(e)||e in t||(t[e]=M[e]);x.push(t)},pluginEvent:function(e,n,o){var t=this;this.eventCanceled=!1,o.cancel=function(){t.eventCanceled=!0};var i=e+"Global";x.forEach(function(t){n[t.pluginName]&&(n[t.pluginName][i]&&n[t.pluginName][i](I({sortable:n},o)),n.options[t.pluginName]&&n[t.pluginName][e]&&n[t.pluginName][e](I({sortable:n},o)))})},initializePlugins:function(o,i,r,t){for(var e in x.forEach(function(t){var e=t.pluginName;if(o.options[e]||t.initializeByDefault){var n=new t(o,i,o.options);n.sortable=o,n.options=o.options,o[e]=n,a(r,n.defaults)}}),o.options)if(o.options.hasOwnProperty(e)){var n=this.modifyOption(o,e,o.options[e]);void 0!==n&&(o.options[e]=n)}},getEventProperties:function(e,n){var o={};return x.forEach(function(t){"function"==typeof t.eventProperties&&a(o,t.eventProperties.call(n[t.pluginName],e))}),o},modifyOption:function(e,n,o){var i;return x.forEach(function(t){e[t.pluginName]&&t.optionListeners&&"function"==typeof t.optionListeners[n]&&(i=t.optionListeners[n].call(e[t.pluginName],o))}),i}};function A(t){var e=t.sortable,n=t.rootEl,o=t.name,i=t.targetEl,r=t.cloneEl,a=t.toEl,l=t.fromEl,s=t.oldIndex,c=t.newIndex,u=t.oldDraggableIndex,d=t.newDraggableIndex,h=t.originalEvent,f=t.putSortable,p=t.extraEventProperties;if(e=e||n&&n[j]){var g,v=e.options,m="on"+o.charAt(0).toUpperCase()+o.substr(1);!window.CustomEvent||w||E?(g=document.createEvent("Event")).initEvent(o,!0,!0):g=new CustomEvent(o,{bubbles:!0,cancelable:!0}),g.to=a||n,g.from=l||n,g.item=i||n,g.clone=r,g.oldIndex=s,g.newIndex=c,g.oldDraggableIndex=u,g.newDraggableIndex=d,g.originalEvent=h,g.pullMode=f?f.lastPutMode:void 0;var b=I({},p,O.getEventProperties(o,e));for(var y in b)g[y]=b[y];n&&n.dispatchEvent(g),v[m]&&v[m].call(e,g)}}function K(t,e,n){var o=2<arguments.length&&void 0!==n?n:{},i=o.evt,r=l(o,["evt"]);O.pluginEvent.bind(Rt)(t,e,I({dragEl:z,parentEl:G,ghostEl:U,rootEl:q,nextEl:V,lastDownEl:Z,cloneEl:Q,cloneHidden:$,dragStarted:dt,putSortable:it,activeSortable:Rt.active,originalEvent:i,oldIndex:J,oldDraggableIndex:et,newIndex:tt,newDraggableIndex:nt,hideGhostForTarget:Nt,unhideGhostForTarget:It,cloneNowHidden:function(){$=!0},cloneNowShown:function(){$=!1},dispatchSortableEvent:function(t){W({sortable:e,name:t,originalEvent:i})}},r))}function W(t){A(I({putSortable:it,cloneEl:Q,targetEl:z,rootEl:q,oldIndex:J,oldDraggableIndex:et,newIndex:tt,newDraggableIndex:nt},t))}var z,G,U,q,V,Z,Q,$,J,tt,et,nt,ot,it,rt,at,lt,st,ct,ut,dt,ht,ft,pt,gt,vt=!1,mt=!1,bt=[],yt=!1,wt=!1,Et=[],Dt=!1,St=[],_t="undefined"!=typeof document,Ct=n,Tt=E||w?"cssFloat":"float",xt=_t&&!i&&!n&&"draggable"in document.createElement("div"),Mt=function(){if(_t){if(w)return!1;var t=document.createElement("x");return t.style.cssText="pointer-events:auto","auto"===t.style.pointerEvents}}(),Ot=function(t,e){var n=R(t),o=parseInt(n.width)-parseInt(n.paddingLeft)-parseInt(n.paddingRight)-parseInt(n.borderLeftWidth)-parseInt(n.borderRightWidth),i=m(t,0,e),r=m(t,1,e),a=i&&R(i),l=r&&R(r),s=a&&parseInt(a.marginLeft)+parseInt(a.marginRight)+X(i).width,c=l&&parseInt(l.marginLeft)+parseInt(l.marginRight)+X(r).width;if("flex"===n.display)return"column"===n.flexDirection||"column-reverse"===n.flexDirection?"vertical":"horizontal";if("grid"===n.display)return n.gridTemplateColumns.split(" ").length<=1?"vertical":"horizontal";if(i&&a.float&&"none"!==a.float){var u="left"===a.float?"left":"right";return!r||"both"!==l.clear&&l.clear!==u?"horizontal":"vertical"}return i&&("block"===a.display||"flex"===a.display||"table"===a.display||"grid"===a.display||o<=s&&"none"===n[Tt]||r&&"none"===n[Tt]&&o<s+c)?"vertical":"horizontal"},At=function(t){function s(a,l){return function(t,e,n,o){var i=t.options.group.name&&e.options.group.name&&t.options.group.name===e.options.group.name;if(null==a&&(l||i))return!0;if(null==a||!1===a)return!1;if(l&&"clone"===a)return a;if("function"==typeof a)return s(a(t,e,n,o),l)(t,e,n,o);var r=(l?t:e).options.group.name;return!0===a||"string"==typeof a&&a===r||a.join&&-1<a.indexOf(r)}}var e={},n=t.group;n&&"object"==o(n)||(n={name:n}),e.name=n.name,e.checkPull=s(n.pull,!0),e.checkPut=s(n.put),e.revertClone=n.revertClone,t.group=e},Nt=function(){!Mt&&U&&R(U,"display","none")},It=function(){!Mt&&U&&R(U,"display","")};_t&&document.addEventListener("click",function(t){if(mt)return t.preventDefault(),t.stopPropagation&&t.stopPropagation(),t.stopImmediatePropagation&&t.stopImmediatePropagation(),mt=!1},!0);function Pt(t){if(z){var e=function(r,a){var l;return bt.some(function(t){if(!B(t)){var e=X(t),n=t[j].options.emptyInsertThreshold,o=r>=e.left-n&&r<=e.right+n,i=a>=e.top-n&&a<=e.bottom+n;return n&&o&&i?l=t:void 0}}),l}((t=t.touches?t.touches[0]:t).clientX,t.clientY);if(e){var n={};for(var o in t)t.hasOwnProperty(o)&&(n[o]=t[o]);n.target=n.rootEl=e,n.preventDefault=void 0,n.stopPropagation=void 0,e[j]._onDragOver(n)}}}function kt(t){z&&z.parentNode[j]._isOutsideThisEl(t.target)}function Rt(t,e){if(!t||!t.nodeType||1!==t.nodeType)throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(t));this.el=t,this.options=e=a({},e),t[j]=this;var n={group:null,sort:!0,disabled:!1,store:null,handle:null,draggable:/^[uo]l$/i.test(t.nodeName)?">li":">*",swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,removeCloneOnHide:!0,direction:function(){return Ot(t,this.options)},ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,easing:null,setData:function(t,e){t.setData("Text",e.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,delayOnTouchOnly:!1,touchStartThreshold:(Number.parseInt?Number:window).parseInt(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:!1!==Rt.supportPointer&&"PointerEvent"in window,emptyInsertThreshold:5};for(var o in O.initializePlugins(this,t,n),n)o in e||(e[o]=n[o]);for(var i in At(e),this)"_"===i.charAt(0)&&"function"==typeof this[i]&&(this[i]=this[i].bind(this));this.nativeDraggable=!e.forceFallback&&xt,this.nativeDraggable&&(this.options.touchStartThreshold=1),e.supportPointer?u(t,"pointerdown",this._onTapStart):(u(t,"mousedown",this._onTapStart),u(t,"touchstart",this._onTapStart)),this.nativeDraggable&&(u(t,"dragover",this),u(t,"dragenter",this)),bt.push(this.el),e.store&&e.store.get&&this.sort(e.store.get(this)||[]),a(this,T())}function Xt(t,e,n,o,i,r,a,l){var s,c,u=t[j],d=u.options.onMove;return!window.CustomEvent||w||E?(s=document.createEvent("Event")).initEvent("move",!0,!0):s=new CustomEvent("move",{bubbles:!0,cancelable:!0}),s.to=e,s.from=t,s.dragged=n,s.draggedRect=o,s.related=i||e,s.relatedRect=r||X(e),s.willInsertAfter=l,s.originalEvent=a,t.dispatchEvent(s),d&&(c=d.call(u,s,a)),c}function Yt(t){t.draggable=!1}function Bt(){Dt=!1}function Ft(t){for(var e=t.tagName+t.className+t.src+t.href+t.textContent,n=e.length,o=0;n--;)o+=e.charCodeAt(n);return o.toString(36)}function Ht(t){return setTimeout(t,0)}function Lt(t){return clearTimeout(t)}Rt.prototype={constructor:Rt,_isOutsideThisEl:function(t){this.el.contains(t)||t===this.el||(ht=null)},_getDirection:function(t,e){return"function"==typeof this.options.direction?this.options.direction.call(this,t,e,z):this.options.direction},_onTapStart:function(e){if(e.cancelable){var n=this,o=this.el,t=this.options,i=t.preventOnFilter,r=e.type,a=e.touches&&e.touches[0]||e.pointerType&&"touch"===e.pointerType&&e,l=(a||e).target,s=e.target.shadowRoot&&(e.path&&e.path[0]||e.composedPath&&e.composedPath()[0])||l,c=t.filter;if(function(t){St.length=0;var e=t.getElementsByTagName("input"),n=e.length;for(;n--;){var o=e[n];o.checked&&St.push(o)}}(o),!z&&!(/mousedown|pointerdown/.test(r)&&0!==e.button||t.disabled||s.isContentEditable||(l=P(l,t.draggable,o,!1))&&l.animated||Z===l)){if(J=F(l),et=F(l,t.draggable),"function"==typeof c){if(c.call(this,e,l,this))return W({sortable:n,rootEl:s,name:"filter",targetEl:l,toEl:o,fromEl:o}),K("filter",n,{evt:e}),void(i&&e.cancelable&&e.preventDefault())}else if(c&&(c=c.split(",").some(function(t){if(t=P(s,t.trim(),o,!1))return W({sortable:n,rootEl:t,name:"filter",targetEl:l,fromEl:o,toEl:o}),K("filter",n,{evt:e}),!0})))return void(i&&e.cancelable&&e.preventDefault());t.handle&&!P(s,t.handle,o,!1)||this._prepareDragStart(e,a,l)}}},_prepareDragStart:function(t,e,n){var o,i=this,r=i.el,a=i.options,l=r.ownerDocument;if(n&&!z&&n.parentNode===r){var s=X(n);if(q=r,G=(z=n).parentNode,V=z.nextSibling,Z=n,ot=a.group,rt={target:Rt.dragged=z,clientX:(e||t).clientX,clientY:(e||t).clientY},ct=rt.clientX-s.left,ut=rt.clientY-s.top,this._lastX=(e||t).clientX,this._lastY=(e||t).clientY,z.style["will-change"]="all",o=function(){K("delayEnded",i,{evt:t}),Rt.eventCanceled?i._onDrop():(i._disableDelayedDragEvents(),!c&&i.nativeDraggable&&(z.draggable=!0),i._triggerDragStart(t,e),W({sortable:i,name:"choose",originalEvent:t}),k(z,a.chosenClass,!0))},a.ignore.split(",").forEach(function(t){g(z,t.trim(),Yt)}),u(l,"dragover",Pt),u(l,"mousemove",Pt),u(l,"touchmove",Pt),u(l,"mouseup",i._onDrop),u(l,"touchend",i._onDrop),u(l,"touchcancel",i._onDrop),c&&this.nativeDraggable&&(this.options.touchStartThreshold=4,z.draggable=!0),K("delayStart",this,{evt:t}),!a.delay||a.delayOnTouchOnly&&!e||this.nativeDraggable&&(E||w))o();else{if(Rt.eventCanceled)return void this._onDrop();u(l,"mouseup",i._disableDelayedDrag),u(l,"touchend",i._disableDelayedDrag),u(l,"touchcancel",i._disableDelayedDrag),u(l,"mousemove",i._delayedDragTouchMoveHandler),u(l,"touchmove",i._delayedDragTouchMoveHandler),a.supportPointer&&u(l,"pointermove",i._delayedDragTouchMoveHandler),i._dragStartTimer=setTimeout(o,a.delay)}}},_delayedDragTouchMoveHandler:function(t){var e=t.touches?t.touches[0]:t;Math.max(Math.abs(e.clientX-this._lastX),Math.abs(e.clientY-this._lastY))>=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){z&&Yt(z),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var t=this.el.ownerDocument;d(t,"mouseup",this._disableDelayedDrag),d(t,"touchend",this._disableDelayedDrag),d(t,"touchcancel",this._disableDelayedDrag),d(t,"mousemove",this._delayedDragTouchMoveHandler),d(t,"touchmove",this._delayedDragTouchMoveHandler),d(t,"pointermove",this._delayedDragTouchMoveHandler)},_triggerDragStart:function(t,e){e=e||"touch"==t.pointerType&&t,!this.nativeDraggable||e?this.options.supportPointer?u(document,"pointermove",this._onTouchMove):u(document,e?"touchmove":"mousemove",this._onTouchMove):(u(z,"dragend",this),u(q,"dragstart",this._onDragStart));try{document.selection?Ht(function(){document.selection.empty()}):window.getSelection().removeAllRanges()}catch(t){}},_dragStarted:function(t,e){if(vt=!1,q&&z){K("dragStarted",this,{evt:e}),this.nativeDraggable&&u(document,"dragover",kt);var n=this.options;t||k(z,n.dragClass,!1),k(z,n.ghostClass,!0),Rt.active=this,t&&this._appendGhost(),W({sortable:this,name:"start",originalEvent:e})}else this._nulling()},_emulateDragOver:function(){if(at){this._lastX=at.clientX,this._lastY=at.clientY,Nt();for(var t=document.elementFromPoint(at.clientX,at.clientY),e=t;t&&t.shadowRoot&&(t=t.shadowRoot.elementFromPoint(at.clientX,at.clientY))!==e;)e=t;if(z.parentNode[j]._isOutsideThisEl(t),e)do{if(e[j]){if(e[j]._onDragOver({clientX:at.clientX,clientY:at.clientY,target:t,rootEl:e})&&!this.options.dragoverBubble)break}t=e}while(e=e.parentNode);It()}},_onTouchMove:function(t){if(rt){var e=this.options,n=e.fallbackTolerance,o=e.fallbackOffset,i=t.touches?t.touches[0]:t,r=U&&v(U,!0),a=U&&r&&r.a,l=U&&r&&r.d,s=Ct&>&&b(gt),c=(i.clientX-rt.clientX+o.x)/(a||1)+(s?s[0]-Et[0]:0)/(a||1),u=(i.clientY-rt.clientY+o.y)/(l||1)+(s?s[1]-Et[1]:0)/(l||1);if(!Rt.active&&!vt){if(n&&Math.max(Math.abs(i.clientX-this._lastX),Math.abs(i.clientY-this._lastY))<n)return;this._onDragStart(t,!0)}if(U){r?(r.e+=c-(lt||0),r.f+=u-(st||0)):r={a:1,b:0,c:0,d:1,e:c,f:u};var d="matrix(".concat(r.a,",").concat(r.b,",").concat(r.c,",").concat(r.d,",").concat(r.e,",").concat(r.f,")");R(U,"webkitTransform",d),R(U,"mozTransform",d),R(U,"msTransform",d),R(U,"transform",d),lt=c,st=u,at=i}t.cancelable&&t.preventDefault()}},_appendGhost:function(){if(!U){var t=this.options.fallbackOnBody?document.body:q,e=X(z,!0,Ct,!0,t),n=this.options;if(Ct){for(gt=t;"static"===R(gt,"position")&&"none"===R(gt,"transform")&>!==document;)gt=gt.parentNode;gt!==document.body&>!==document.documentElement?(gt===document&&(gt=N()),e.top+=gt.scrollTop,e.left+=gt.scrollLeft):gt=N(),Et=b(gt)}k(U=z.cloneNode(!0),n.ghostClass,!1),k(U,n.fallbackClass,!0),k(U,n.dragClass,!0),R(U,"transition",""),R(U,"transform",""),R(U,"box-sizing","border-box"),R(U,"margin",0),R(U,"top",e.top),R(U,"left",e.left),R(U,"width",e.width),R(U,"height",e.height),R(U,"opacity","0.8"),R(U,"position",Ct?"absolute":"fixed"),R(U,"zIndex","100000"),R(U,"pointerEvents","none"),Rt.ghost=U,t.appendChild(U),R(U,"transform-origin",ct/parseInt(U.style.width)*100+"% "+ut/parseInt(U.style.height)*100+"%")}},_onDragStart:function(t,e){var n=this,o=t.dataTransfer,i=n.options;K("dragStart",this,{evt:t}),Rt.eventCanceled?this._onDrop():(K("setupClone",this),Rt.eventCanceled||((Q=S(z)).draggable=!1,Q.style["will-change"]="",this._hideClone(),k(Q,this.options.chosenClass,!1),Rt.clone=Q),n.cloneId=Ht(function(){K("clone",n),Rt.eventCanceled||(n.options.removeCloneOnHide||q.insertBefore(Q,z),n._hideClone(),W({sortable:n,name:"clone"}))}),e||k(z,i.dragClass,!0),e?(mt=!0,n._loopId=setInterval(n._emulateDragOver,50)):(d(document,"mouseup",n._onDrop),d(document,"touchend",n._onDrop),d(document,"touchcancel",n._onDrop),o&&(o.effectAllowed="move",i.setData&&i.setData.call(n,o,z)),u(document,"drop",n),R(z,"transform","translateZ(0)")),vt=!0,n._dragStartId=Ht(n._dragStarted.bind(n,e,t)),u(document,"selectstart",n),dt=!0,s&&R(document.body,"user-select","none"))},_onDragOver:function(n){var o,i,r,a,l=this.el,s=n.target,e=this.options,t=e.group,c=Rt.active,u=ot===t,d=e.sort,h=it||c,f=this,p=!1;if(!Dt){if(void 0!==n.preventDefault&&n.cancelable&&n.preventDefault(),s=P(s,e.draggable,l,!0),M("dragOver"),Rt.eventCanceled)return p;if(z.contains(n.target)||s.animated&&s.animatingX&&s.animatingY||f._ignoreWhileAnimating===s)return A(!1);if(mt=!1,c&&!e.disabled&&(u?d||(r=!q.contains(z)):it===this||(this.lastPutMode=ot.checkPull(this,c,z,n))&&t.checkPut(this,c,z,n))){if(a="vertical"===this._getDirection(n,s),o=X(z),M("dragOverValid"),Rt.eventCanceled)return p;if(r)return G=q,O(),this._hideClone(),M("revert"),Rt.eventCanceled||(V?q.insertBefore(z,V):q.appendChild(z)),A(!0);var g=B(l,e.draggable);if(!g||function(t,e,n){var o=X(B(n.el,n.options.draggable));return e?t.clientX>o.right+10||t.clientX<=o.right&&t.clientY>o.bottom&&t.clientX>=o.left:t.clientX>o.right&&t.clientY>o.top||t.clientX<=o.right&&t.clientY>o.bottom+10}(n,a,this)&&!g.animated){if(g===z)return A(!1);if(g&&l===n.target&&(s=g),s&&(i=X(s)),!1!==Xt(q,l,z,o,s,i,n,!!s))return O(),l.appendChild(z),G=l,N(),A(!0)}else if(s.parentNode===l){i=X(s);var v,m,b,y=z.parentNode!==l,w=!function(t,e,n){var o=n?t.left:t.top,i=n?t.right:t.bottom,r=n?t.width:t.height,a=n?e.left:e.top,l=n?e.right:e.bottom,s=n?e.width:e.height;return o===a||i===l||o+r/2===a+s/2}(z.animated&&z.toRect||o,s.animated&&s.toRect||i,a),E=a?"top":"left",D=Y(s,"top","top")||Y(z,"top","top"),S=D?D.scrollTop:void 0;if(ht!==s&&(m=i[E],yt=!1,wt=!w&&e.invertSwap||y),0!==(v=function(t,e,n,o,i,r,a,l){var s=o?t.clientY:t.clientX,c=o?n.height:n.width,u=o?n.top:n.left,d=o?n.bottom:n.right,h=!1;if(!a)if(l&&pt<c*i){if(!yt&&(1===ft?u+c*r/2<s:s<d-c*r/2)&&(yt=!0),yt)h=!0;else if(1===ft?s<u+pt:d-pt<s)return-ft}else if(u+c*(1-i)/2<s&&s<d-c*(1-i)/2)return function(t){return F(z)<F(t)?1:-1}(e);if((h=h||a)&&(s<u+c*r/2||d-c*r/2<s))return u+c/2<s?1:-1;return 0}(n,s,i,a,w?1:e.swapThreshold,null==e.invertedSwapThreshold?e.swapThreshold:e.invertedSwapThreshold,wt,ht===s)))for(var _=F(z);_-=v,(b=G.children[_])&&("none"===R(b,"display")||b===U););if(0===v||b===s)return A(!1);ft=v;var C=(ht=s).nextElementSibling,T=!1,x=Xt(q,l,z,o,s,i,n,T=1===v);if(!1!==x)return 1!==x&&-1!==x||(T=1===x),Dt=!0,setTimeout(Bt,30),O(),T&&!C?l.appendChild(z):s.parentNode.insertBefore(z,T?C:s),D&&L(D,0,S-D.scrollTop),G=z.parentNode,void 0===m||wt||(pt=Math.abs(m-X(s)[E])),N(),A(!0)}if(l.contains(z))return A(!1)}return!1}function M(t,e){K(t,f,I({evt:n,isOwner:u,axis:a?"vertical":"horizontal",revert:r,dragRect:o,targetRect:i,canSort:d,fromSortable:h,target:s,completed:A,onMove:function(t,e){return Xt(q,l,z,o,t,X(t),n,e)},changed:N},e))}function O(){M("dragOverAnimationCapture"),f.captureAnimationState(),f!==h&&h.captureAnimationState()}function A(t){return M("dragOverCompleted",{insertion:t}),t&&(u?c._hideClone():c._showClone(f),f!==h&&(k(z,it?it.options.ghostClass:c.options.ghostClass,!1),k(z,e.ghostClass,!0)),it!==f&&f!==Rt.active?it=f:f===Rt.active&&it&&(it=null),h===f&&(f._ignoreWhileAnimating=s),f.animateAll(function(){M("dragOverAnimationComplete"),f._ignoreWhileAnimating=null}),f!==h&&(h.animateAll(),h._ignoreWhileAnimating=null)),(s===z&&!z.animated||s===l&&!s.animated)&&(ht=null),e.dragoverBubble||n.rootEl||s===document||(z.parentNode[j]._isOutsideThisEl(n.target),t||Pt(n)),!e.dragoverBubble&&n.stopPropagation&&n.stopPropagation(),p=!0}function N(){tt=F(z),nt=F(z,e.draggable),W({sortable:f,name:"change",toEl:l,newIndex:tt,newDraggableIndex:nt,originalEvent:n})}},_ignoreWhileAnimating:null,_offMoveEvents:function(){d(document,"mousemove",this._onTouchMove),d(document,"touchmove",this._onTouchMove),d(document,"pointermove",this._onTouchMove),d(document,"dragover",Pt),d(document,"mousemove",Pt),d(document,"touchmove",Pt)},_offUpEvents:function(){var t=this.el.ownerDocument;d(t,"mouseup",this._onDrop),d(t,"touchend",this._onDrop),d(t,"pointerup",this._onDrop),d(t,"touchcancel",this._onDrop),d(document,"selectstart",this)},_onDrop:function(t){var e=this.el,n=this.options;tt=F(z),nt=F(z,n.draggable),K("drop",this,{evt:t}),G=z&&z.parentNode,tt=F(z),nt=F(z,n.draggable),Rt.eventCanceled||(yt=wt=vt=!1,clearInterval(this._loopId),clearTimeout(this._dragStartTimer),Lt(this.cloneId),Lt(this._dragStartId),this.nativeDraggable&&(d(document,"drop",this),d(e,"dragstart",this._onDragStart)),this._offMoveEvents(),this._offUpEvents(),s&&R(document.body,"user-select",""),R(z,"transform",""),t&&(dt&&(t.cancelable&&t.preventDefault(),n.dropBubble||t.stopPropagation()),U&&U.parentNode&&U.parentNode.removeChild(U),(q===G||it&&"clone"!==it.lastPutMode)&&Q&&Q.parentNode&&Q.parentNode.removeChild(Q),z&&(this.nativeDraggable&&d(z,"dragend",this),Yt(z),z.style["will-change"]="",dt&&!vt&&k(z,it?it.options.ghostClass:this.options.ghostClass,!1),k(z,this.options.chosenClass,!1),W({sortable:this,name:"unchoose",toEl:G,newIndex:null,newDraggableIndex:null,originalEvent:t}),q!==G?(0<=tt&&(W({rootEl:G,name:"add",toEl:G,fromEl:q,originalEvent:t}),W({sortable:this,name:"remove",toEl:G,originalEvent:t}),W({rootEl:G,name:"sort",toEl:G,fromEl:q,originalEvent:t}),W({sortable:this,name:"sort",toEl:G,originalEvent:t})),it&&it.save()):tt!==J&&0<=tt&&(W({sortable:this,name:"update",toEl:G,originalEvent:t}),W({sortable:this,name:"sort",toEl:G,originalEvent:t})),Rt.active&&(null!=tt&&-1!==tt||(tt=J,nt=et),W({sortable:this,name:"end",toEl:G,originalEvent:t}),this.save())))),this._nulling()},_nulling:function(){K("nulling",this),q=z=G=U=V=Q=Z=$=rt=at=dt=tt=nt=J=et=ht=ft=it=ot=Rt.dragged=Rt.ghost=Rt.clone=Rt.active=null,St.forEach(function(t){t.checked=!0}),St.length=lt=st=0},handleEvent:function(t){switch(t.type){case"drop":case"dragend":this._onDrop(t);break;case"dragenter":case"dragover":z&&(this._onDragOver(t),function(t){t.dataTransfer&&(t.dataTransfer.dropEffect="move");t.cancelable&&t.preventDefault()}(t));break;case"selectstart":t.preventDefault()}},toArray:function(){for(var t,e=[],n=this.el.children,o=0,i=n.length,r=this.options;o<i;o++)P(t=n[o],r.draggable,this.el,!1)&&e.push(t.getAttribute(r.dataIdAttr)||Ft(t));return e},sort:function(t){var o={},i=this.el;this.toArray().forEach(function(t,e){var n=i.children[e];P(n,this.options.draggable,i,!1)&&(o[t]=n)},this),t.forEach(function(t){o[t]&&(i.removeChild(o[t]),i.appendChild(o[t]))})},save:function(){var t=this.options.store;t&&t.set&&t.set(this)},closest:function(t,e){return P(t,e||this.options.draggable,this.el,!1)},option:function(t,e){var n=this.options;if(void 0===e)return n[t];var o=O.modifyOption(this,t,e);n[t]=void 0!==o?o:e,"group"===t&&At(n)},destroy:function(){K("destroy",this);var t=this.el;t[j]=null,d(t,"mousedown",this._onTapStart),d(t,"touchstart",this._onTapStart),d(t,"pointerdown",this._onTapStart),this.nativeDraggable&&(d(t,"dragover",this),d(t,"dragenter",this)),Array.prototype.forEach.call(t.querySelectorAll("[draggable]"),function(t){t.removeAttribute("draggable")}),this._onDrop(),this._disableDelayedDragEvents(),bt.splice(bt.indexOf(this.el),1),this.el=t=null},_hideClone:function(){if(!$){if(K("hideClone",this),Rt.eventCanceled)return;R(Q,"display","none"),this.options.removeCloneOnHide&&Q.parentNode&&Q.parentNode.removeChild(Q),$=!0}},_showClone:function(t){if("clone"===t.lastPutMode){if($){if(K("showClone",this),Rt.eventCanceled)return;q.contains(z)&&!this.options.group.revertClone?q.insertBefore(Q,z):V?q.insertBefore(Q,V):q.appendChild(Q),this.options.group.revertClone&&this.animate(z,Q),R(Q,"display",""),$=!1}}else this._hideClone()}},_t&&u(document,"touchmove",function(t){(Rt.active||vt)&&t.cancelable&&t.preventDefault()}),Rt.utils={on:u,off:d,css:R,find:g,is:function(t,e){return!!P(t,e,t,!1)},extend:function(t,e){if(t&&e)for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t},throttle:D,closest:P,toggleClass:k,clone:S,index:F,nextTick:Ht,cancelNextTick:Lt,detectDirection:Ot,getChild:m},Rt.get=function(t){return t[j]},Rt.mount=function(){for(var t=arguments.length,e=new Array(t),n=0;n<t;n++)e[n]=arguments[n];e[0].constructor===Array&&(e=e[0]),e.forEach(function(t){if(!t.prototype||!t.prototype.constructor)throw"Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(t));t.utils&&(Rt.utils=I({},Rt.utils,t.utils)),O.mount(t)})},Rt.create=function(t,e){return new Rt(t,e)};var jt,Kt,Wt,zt,Gt,Ut,qt=[],Vt=!(Rt.version="1.10.2");function Zt(){qt.forEach(function(t){clearInterval(t.pid)}),qt=[]}function Qt(){clearInterval(Ut)}function $t(t){var e=t.originalEvent,n=t.putSortable,o=t.dragEl,i=t.activeSortable,r=t.dispatchSortableEvent,a=t.hideGhostForTarget,l=t.unhideGhostForTarget;if(e){var s=n||i;a();var c=e.changedTouches&&e.changedTouches.length?e.changedTouches[0]:e,u=document.elementFromPoint(c.clientX,c.clientY);l(),s&&!s.el.contains(u)&&(r("spill"),this.onSpill({dragEl:o,putSortable:n}))}}var Jt,te=D(function(n,t,e,o){if(t.scroll){var i,r=(n.touches?n.touches[0]:n).clientX,a=(n.touches?n.touches[0]:n).clientY,l=t.scrollSensitivity,s=t.scrollSpeed,c=N(),u=!1;Kt!==e&&(Kt=e,Zt(),jt=t.scroll,i=t.scrollFn,!0===jt&&(jt=H(e,!0)));var d=0,h=jt;do{var f=h,p=X(f),g=p.top,v=p.bottom,m=p.left,b=p.right,y=p.width,w=p.height,E=void 0,D=void 0,S=f.scrollWidth,_=f.scrollHeight,C=R(f),T=f.scrollLeft,x=f.scrollTop;D=f===c?(E=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX||"visible"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY||"visible"===C.overflowY)):(E=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY));var M=E&&(Math.abs(b-r)<=l&&T+y<S)-(Math.abs(m-r)<=l&&!!T),O=D&&(Math.abs(v-a)<=l&&x+w<_)-(Math.abs(g-a)<=l&&!!x);if(!qt[d])for(var A=0;A<=d;A++)qt[A]||(qt[A]={});qt[d].vx==M&&qt[d].vy==O&&qt[d].el===f||(qt[d].el=f,qt[d].vx=M,qt[d].vy=O,clearInterval(qt[d].pid),0==M&&0==O||(u=!0,qt[d].pid=setInterval(function(){o&&0===this.layer&&Rt.active._onTouchMove(Gt);var t=qt[this.layer].vy?qt[this.layer].vy*s:0,e=qt[this.layer].vx?qt[this.layer].vx*s:0;"function"==typeof i&&"continue"!==i.call(Rt.dragged.parentNode[j],e,t,n,Gt,qt[this.layer].el)||L(qt[this.layer].el,e,t)}.bind({layer:d}),24))),d++}while(t.bubbleScroll&&h!==c&&(h=H(h,!1)));Vt=u}},30);function ee(){}function ne(){}ee.prototype={startIndex:null,dragStart:function(t){var e=t.oldDraggableIndex;this.startIndex=e},onSpill:function(t){var e=t.dragEl,n=t.putSortable;this.sortable.captureAnimationState(),n&&n.captureAnimationState();var o=m(this.sortable.el,this.startIndex,this.options);o?this.sortable.el.insertBefore(e,o):this.sortable.el.appendChild(e),this.sortable.animateAll(),n&&n.animateAll()},drop:$t},a(ee,{pluginName:"revertOnSpill"}),ne.prototype={onSpill:function(t){var e=t.dragEl,n=t.putSortable||this.sortable;n.captureAnimationState(),e.parentNode&&e.parentNode.removeChild(e),n.animateAll()},drop:$t},a(ne,{pluginName:"removeOnSpill"});var oe,ie,re,ae,le,se=[],ce=[],ue=!1,de=!1,he=!1;function fe(o,i){ce.forEach(function(t,e){var n=i.children[t.sortableIndex+(o?Number(e):0)];n?i.insertBefore(t,n):i.appendChild(t)})}function pe(){se.forEach(function(t){t!==re&&t.parentNode&&t.parentNode.removeChild(t)})}return Rt.mount(new function(){function t(){for(var t in this.defaults={scroll:!0,scrollSensitivity:30,scrollSpeed:10,bubbleScroll:!0},this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this))}return t.prototype={dragStarted:function(t){var e=t.originalEvent;this.sortable.nativeDraggable?u(document,"dragover",this._handleAutoScroll):this.options.supportPointer?u(document,"pointermove",this._handleFallbackAutoScroll):e.touches?u(document,"touchmove",this._handleFallbackAutoScroll):u(document,"mousemove",this._handleFallbackAutoScroll)},dragOverCompleted:function(t){var e=t.originalEvent;this.options.dragOverBubble||e.rootEl||this._handleAutoScroll(e)},drop:function(){this.sortable.nativeDraggable?d(document,"dragover",this._handleAutoScroll):(d(document,"pointermove",this._handleFallbackAutoScroll),d(document,"touchmove",this._handleFallbackAutoScroll),d(document,"mousemove",this._handleFallbackAutoScroll)),Qt(),Zt(),clearTimeout(f),f=void 0},nulling:function(){Gt=Kt=jt=Vt=Ut=Wt=zt=null,qt.length=0},_handleFallbackAutoScroll:function(t){this._handleAutoScroll(t,!0)},_handleAutoScroll:function(e,n){var o=this,i=(e.touches?e.touches[0]:e).clientX,r=(e.touches?e.touches[0]:e).clientY,t=document.elementFromPoint(i,r);if(Gt=e,n||E||w||s){te(e,this.options,t,n);var a=H(t,!0);!Vt||Ut&&i===Wt&&r===zt||(Ut&&Qt(),Ut=setInterval(function(){var t=H(document.elementFromPoint(i,r),!0);t!==a&&(a=t,Zt()),te(e,o.options,t,n)},10),Wt=i,zt=r)}else{if(!this.options.bubbleScroll||H(t,!0)===N())return void Zt();te(e,this.options,H(t,!1),!1)}}},a(t,{pluginName:"scroll",initializeByDefault:!0})}),Rt.mount(ne,ee),Rt.mount(new function(){function t(){this.defaults={swapClass:"sortable-swap-highlight"}}return t.prototype={dragStart:function(t){var e=t.dragEl;Jt=e},dragOverValid:function(t){var e=t.completed,n=t.target,o=t.onMove,i=t.activeSortable,r=t.changed,a=t.cancel;if(i.options.swap){var l=this.sortable.el,s=this.options;if(n&&n!==l){var c=Jt;Jt=!1!==o(n)?(k(n,s.swapClass,!0),n):null,c&&c!==Jt&&k(c,s.swapClass,!1)}r(),e(!0),a()}},drop:function(t){var e=t.activeSortable,n=t.putSortable,o=t.dragEl,i=n||this.sortable,r=this.options;Jt&&k(Jt,r.swapClass,!1),Jt&&(r.swap||n&&n.options.swap)&&o!==Jt&&(i.captureAnimationState(),i!==e&&e.captureAnimationState(),function(t,e){var n,o,i=t.parentNode,r=e.parentNode;if(!i||!r||i.isEqualNode(e)||r.isEqualNode(t))return;n=F(t),o=F(e),i.isEqualNode(r)&&n<o&&o++;i.insertBefore(e,i.children[n]),r.insertBefore(t,r.children[o])}(o,Jt),i.animateAll(),i!==e&&e.animateAll())},nulling:function(){Jt=null}},a(t,{pluginName:"swap",eventProperties:function(){return{swapItem:Jt}}})}),Rt.mount(new function(){function t(o){for(var t in this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this));o.options.supportPointer?u(document,"pointerup",this._deselectMultiDrag):(u(document,"mouseup",this._deselectMultiDrag),u(document,"touchend",this._deselectMultiDrag)),u(document,"keydown",this._checkKeyDown),u(document,"keyup",this._checkKeyUp),this.defaults={selectedClass:"sortable-selected",multiDragKey:null,setData:function(t,e){var n="";se.length&&ie===o?se.forEach(function(t,e){n+=(e?", ":"")+t.textContent}):n=e.textContent,t.setData("Text",n)}}}return t.prototype={multiDragKeyDown:!1,isMultiDrag:!1,delayStartGlobal:function(t){var e=t.dragEl;re=e},delayEnded:function(){this.isMultiDrag=~se.indexOf(re)},setupClone:function(t){var e=t.sortable,n=t.cancel;if(this.isMultiDrag){for(var o=0;o<se.length;o++)ce.push(S(se[o])),ce[o].sortableIndex=se[o].sortableIndex,ce[o].draggable=!1,ce[o].style["will-change"]="",k(ce[o],this.options.selectedClass,!1),se[o]===re&&k(ce[o],this.options.chosenClass,!1);e._hideClone(),n()}},clone:function(t){var e=t.sortable,n=t.rootEl,o=t.dispatchSortableEvent,i=t.cancel;this.isMultiDrag&&(this.options.removeCloneOnHide||se.length&&ie===e&&(fe(!0,n),o("clone"),i()))},showClone:function(t){var e=t.cloneNowShown,n=t.rootEl,o=t.cancel;this.isMultiDrag&&(fe(!1,n),ce.forEach(function(t){R(t,"display","")}),e(),le=!1,o())},hideClone:function(t){var e=this,n=(t.sortable,t.cloneNowHidden),o=t.cancel;this.isMultiDrag&&(ce.forEach(function(t){R(t,"display","none"),e.options.removeCloneOnHide&&t.parentNode&&t.parentNode.removeChild(t)}),n(),le=!0,o())},dragStartGlobal:function(t){t.sortable;!this.isMultiDrag&&ie&&ie.multiDrag._deselectMultiDrag(),se.forEach(function(t){t.sortableIndex=F(t)}),se=se.sort(function(t,e){return t.sortableIndex-e.sortableIndex}),he=!0},dragStarted:function(t){var e=this,n=t.sortable;if(this.isMultiDrag){if(this.options.sort&&(n.captureAnimationState(),this.options.animation)){se.forEach(function(t){t!==re&&R(t,"position","absolute")});var o=X(re,!1,!0,!0);se.forEach(function(t){t!==re&&_(t,o)}),ue=de=!0}n.animateAll(function(){ue=de=!1,e.options.animation&&se.forEach(function(t){C(t)}),e.options.sort&&pe()})}},dragOver:function(t){var e=t.target,n=t.completed,o=t.cancel;de&&~se.indexOf(e)&&(n(!1),o())},revert:function(t){var e=t.fromSortable,n=t.rootEl,o=t.sortable,i=t.dragRect;1<se.length&&(se.forEach(function(t){o.addAnimationState({target:t,rect:de?X(t):i}),C(t),t.fromRect=i,e.removeAnimationState(t)}),de=!1,function(o,i){se.forEach(function(t,e){var n=i.children[t.sortableIndex+(o?Number(e):0)];n?i.insertBefore(t,n):i.appendChild(t)})}(!this.options.removeCloneOnHide,n))},dragOverCompleted:function(t){var e=t.sortable,n=t.isOwner,o=t.insertion,i=t.activeSortable,r=t.parentEl,a=t.putSortable,l=this.options;if(o){if(n&&i._hideClone(),ue=!1,l.animation&&1<se.length&&(de||!n&&!i.options.sort&&!a)){var s=X(re,!1,!0,!0);se.forEach(function(t){t!==re&&(_(t,s),r.appendChild(t))}),de=!0}if(!n)if(de||pe(),1<se.length){var c=le;i._showClone(e),i.options.animation&&!le&&c&&ce.forEach(function(t){i.addAnimationState({target:t,rect:ae}),t.fromRect=ae,t.thisAnimationDuration=null})}else i._showClone(e)}},dragOverAnimationCapture:function(t){var e=t.dragRect,n=t.isOwner,o=t.activeSortable;if(se.forEach(function(t){t.thisAnimationDuration=null}),o.options.animation&&!n&&o.multiDrag.isMultiDrag){ae=a({},e);var i=v(re,!0);ae.top-=i.f,ae.left-=i.e}},dragOverAnimationComplete:function(){de&&(de=!1,pe())},drop:function(t){var e=t.originalEvent,n=t.rootEl,o=t.parentEl,i=t.sortable,r=t.dispatchSortableEvent,a=t.oldIndex,l=t.putSortable,s=l||this.sortable;if(e){var c=this.options,u=o.children;if(!he)if(c.multiDragKey&&!this.multiDragKeyDown&&this._deselectMultiDrag(),k(re,c.selectedClass,!~se.indexOf(re)),~se.indexOf(re))se.splice(se.indexOf(re),1),oe=null,A({sortable:i,rootEl:n,name:"deselect",targetEl:re,originalEvt:e});else{if(se.push(re),A({sortable:i,rootEl:n,name:"select",targetEl:re,originalEvt:e}),e.shiftKey&&oe&&i.el.contains(oe)){var d,h,f=F(oe),p=F(re);if(~f&&~p&&f!==p)for(d=f<p?(h=f,p):(h=p,f+1);h<d;h++)~se.indexOf(u[h])||(k(u[h],c.selectedClass,!0),se.push(u[h]),A({sortable:i,rootEl:n,name:"select",targetEl:u[h],originalEvt:e}))}else oe=re;ie=s}if(he&&this.isMultiDrag){if((o[j].options.sort||o!==n)&&1<se.length){var g=X(re),v=F(re,":not(."+this.options.selectedClass+")");if(!ue&&c.animation&&(re.thisAnimationDuration=null),s.captureAnimationState(),!ue&&(c.animation&&(re.fromRect=g,se.forEach(function(t){if(t.thisAnimationDuration=null,t!==re){var e=de?X(t):g;t.fromRect=e,s.addAnimationState({target:t,rect:e})}})),pe(),se.forEach(function(t){u[v]?o.insertBefore(t,u[v]):o.appendChild(t),v++}),a===F(re))){var m=!1;se.forEach(function(t){t.sortableIndex===F(t)||(m=!0)}),m&&r("update")}se.forEach(function(t){C(t)}),s.animateAll()}ie=s}(n===o||l&&"clone"!==l.lastPutMode)&&ce.forEach(function(t){t.parentNode&&t.parentNode.removeChild(t)})}},nullingGlobal:function(){this.isMultiDrag=he=!1,ce.length=0},destroyGlobal:function(){this._deselectMultiDrag(),d(document,"pointerup",this._deselectMultiDrag),d(document,"mouseup",this._deselectMultiDrag),d(document,"touchend",this._deselectMultiDrag),d(document,"keydown",this._checkKeyDown),d(document,"keyup",this._checkKeyUp)},_deselectMultiDrag:function(t){if(!(void 0!==he&&he||ie!==this.sortable||t&&P(t.target,this.options.draggable,this.sortable.el,!1)||t&&0!==t.button))for(;se.length;){var e=se[0];k(e,this.options.selectedClass,!1),se.shift(),A({sortable:this.sortable,rootEl:this.sortable.el,name:"deselect",targetEl:e,originalEvt:t})}},_checkKeyDown:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!0)},_checkKeyUp:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!1)}},a(t,{pluginName:"multiDrag",utils:{select:function(t){var e=t.parentNode[j];e&&e.options.multiDrag&&!~se.indexOf(t)&&(ie&&ie!==e&&(ie.multiDrag._deselectMultiDrag(),ie=e),k(t,e.options.selectedClass,!0),se.push(t))},deselect:function(t){var e=t.parentNode[j],n=se.indexOf(t);e&&e.options.multiDrag&&~n&&(k(t,e.options.selectedClass,!1),se.splice(n,1))}},eventProperties:function(){var n=this,o=[],i=[];return se.forEach(function(t){var e;o.push({multiDragElement:t,index:t.sortableIndex}),e=de&&t!==re?-1:de?F(t,":not(."+n.options.selectedClass+")"):F(t),i.push({multiDragElement:t,index:e})}),{items:e(se),clones:[].concat(ce),oldIndicies:o,newIndicies:i}},optionListeners:{multiDragKey:function(t){return"ctrl"===(t=t.toLowerCase())?t="Control":1<t.length&&(t=t.charAt(0).toUpperCase()+t.substr(1)),t}}})}),Rt}); |
New file |
| | |
| | | |
| | | /* 样式加载完毕的标识 */ |
| | | html #layuicss-cron { |
| | | display: none; |
| | | position: absolute; |
| | | width: 1989px; |
| | | } |
| | | |
| | | |
| | | /* 主体结构 */ |
| | | .layui-cron { |
| | | position: absolute; |
| | | z-index: 1000; |
| | | margin: 5px 0; |
| | | border-radius: 2px; |
| | | font-size: 14px; |
| | | -webkit-animation-duration: 0.3s; |
| | | animation-duration: 0.3s; |
| | | -webkit-animation-fill-mode: both; |
| | | animation-fill-mode: both; |
| | | background-color: white; |
| | | display: flex; |
| | | flex-direction: column; |
| | | box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 5px 0px; |
| | | -webkit-animation-name: cron-upbit; |
| | | animation-name: cron-upbit; |
| | | border: 1px solid #e6e6e6; |
| | | } |
| | | |
| | | @-webkit-keyframes cron-upbit { |
| | | |
| | | /* 微微往上滑入 */ |
| | | from { |
| | | -webkit-transform: translate3d(0, 20px, 0); |
| | | opacity: 0.3; |
| | | } |
| | | |
| | | to { |
| | | -webkit-transform: translate3d(0, 0, 0); |
| | | opacity: 1; |
| | | } |
| | | } |
| | | |
| | | @keyframes cron-upbit { |
| | | from { |
| | | transform: translate3d(0, 20px, 0); |
| | | opacity: 0.3; |
| | | } |
| | | |
| | | to { |
| | | transform: translate3d(0, 0, 0); |
| | | opacity: 1; |
| | | } |
| | | } |
| | | |
| | | /* tabs */ |
| | | .layui-cron>.layui-tab { |
| | | margin: 0; |
| | | box-shadow: none; |
| | | border: none; |
| | | } |
| | | |
| | | /* 表达式 */ |
| | | .cron-title { |
| | | font-weight: 700; |
| | | font-size: 14px; |
| | | margin: 10px; |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .cron-box { |
| | | margin: 10px; |
| | | } |
| | | |
| | | .cron-box+.cron-box { |
| | | margin-top: 0; |
| | | } |
| | | |
| | | /* 按钮 */ |
| | | .cron-footer-btns { |
| | | text-align: right; |
| | | } |
| | | |
| | | .cron-footer-btns span { |
| | | height: 26px; |
| | | line-height: 26px; |
| | | margin: 0 0 0 -1px; |
| | | padding: 0 10px; |
| | | border: 1px solid #C9C9C9; |
| | | background-color: #fff; |
| | | white-space: nowrap; |
| | | vertical-align: top; |
| | | border-radius: 2px; |
| | | display: inline-block; |
| | | cursor: pointer; |
| | | font-size: 12px; |
| | | box-sizing: border-box; |
| | | color: #666; |
| | | } |
| | | |
| | | .cron-footer-btns span:hover { |
| | | color: #5FB878; |
| | | } |
| | | |
| | | |
| | | /* 表单 */ |
| | | .layui-cron .layui-form-radio { |
| | | margin-right: 0; |
| | | } |
| | | |
| | | .cron-form { |
| | | line-height: 28px; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .cron-input-mid { |
| | | display: inline-block; |
| | | vertical-align: middle; |
| | | margin-top: 6px; |
| | | background-color: #e5e5e5; |
| | | padding: 0 12px; |
| | | height: 28px; |
| | | line-height: 28px; |
| | | border: 1px solid #ccc; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .cron-input { |
| | | display: inline-block; |
| | | vertical-align: middle; |
| | | margin-top: 6px; |
| | | padding: 0 8px; |
| | | background-color: #fff; |
| | | border: 1px solid #ccc; |
| | | height: 28px; |
| | | line-height: 28px; |
| | | box-sizing: border-box; |
| | | width: 80px; |
| | | -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; |
| | | -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; |
| | | transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; |
| | | transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; |
| | | transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; |
| | | } |
| | | |
| | | .cron-input:focus { |
| | | outline: 0; |
| | | border: 1px solid #01AAED; |
| | | box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 4px 0px #01AAED; |
| | | translate: 1s; |
| | | } |
| | | |
| | | .layui-cron .layui-form-checkbox[lay-skin="primary"] span { |
| | | padding-right: 10px; |
| | | min-width: 16px; |
| | | } |
| | | |
| | | .layui-cron .layui-form-checkbox[lay-skin="primary"] { |
| | | padding-left: 22px; |
| | | margin-top: 5px; |
| | | } |
| | | .layui-cron input[type=number] { |
| | | -moz-appearance:textfield; |
| | | } |
| | | .layui-cron input[type=number]::-webkit-inner-spin-button, |
| | | .layui-cron input[type=number]::-webkit-outer-spin-button { |
| | | -webkit-appearance: none; |
| | | margin: 0; |
| | | } |
| | | .cron-tips{ |
| | | color: grey; |
| | | line-height: 28px; |
| | | height: 28px; |
| | | display: inline-block; |
| | | vertical-align: middle; |
| | | margin-top: 8px; |
| | | margin-left: 5px; |
| | | } |
New file |
| | |
| | | .layui-layout-admin .layui-logo { |
| | | color : #fff; |
| | | font-size: 20px; |
| | | } |
| | | |
| | | .layui-side-right { |
| | | position : fixed; |
| | | right : 0; |
| | | top : 0; |
| | | bottom : 0; |
| | | z-index : 999; |
| | | width : 350px; |
| | | overflow-x: hidden |
| | | } |
| | | |
| | | .layui-layout-admin .layui-side { |
| | | top : 60px; |
| | | width : 260px; |
| | | overflow-x: hidden |
| | | } |
| | | |
| | | .layui-layout-admin .layui-side-right { |
| | | top : 60px; |
| | | width : 350px; |
| | | overflow-x: hidden |
| | | } |
| | | |
| | | .layui-body { |
| | | position : absolute; |
| | | left : 260px; |
| | | right : 350px; |
| | | top : 0; |
| | | bottom : 0; |
| | | z-index : 998; |
| | | width : auto; |
| | | overflow-y : auto; |
| | | box-sizing : border-box; |
| | | min-width : 250px; |
| | | border-left : 1px solid #e6e6e6; |
| | | border-right: 1px solid #e6e6e6; |
| | | } |
| | | |
| | | .layui-layout-admin .layui-body { |
| | | bottom: 0; |
| | | } |
| | | |
| | | /* components-list*/ |
| | | |
| | | .components-list { |
| | | padding : 4px; |
| | | -webkit-box-sizing: border-box; |
| | | box-sizing : border-box; |
| | | height : 100% |
| | | } |
| | | |
| | | .components-list .components-item { |
| | | display : inline-block; |
| | | width : 49%; |
| | | margin : 0.5%; |
| | | margin-top : 5px; |
| | | -webkit-transition: -webkit-transform 0ms !important; |
| | | transition : -webkit-transform 0ms !important; |
| | | transition : transform 0ms !important; |
| | | transition : transform 0ms, -webkit-transform 0ms !important |
| | | } |
| | | |
| | | .components-draggable { |
| | | padding-bottom: 20px |
| | | } |
| | | |
| | | .components-title { |
| | | font-size: 14px; |
| | | color : #2196f3; |
| | | margin : 6px 2px; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .right-button { |
| | | float: right; |
| | | padding: 1px 3px; |
| | | border: none; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .button--text { |
| | | color: #009688; |
| | | background: 0 0; |
| | | padding-left: 0; |
| | | padding-right: 0; |
| | | font-size: 10px; |
| | | } |
| | | |
| | | .components-title .svg-icon { |
| | | color : #666; |
| | | font-size: 18px |
| | | } |
| | | |
| | | .components-body { |
| | | padding : 8px 10px; |
| | | background : #f6f7ff; |
| | | font-size : 12px; |
| | | cursor : move; |
| | | border : 1px dashed #f6f7ff; |
| | | border-radius: 3px |
| | | } |
| | | |
| | | .components-body .svg-icon { |
| | | color : #777; |
| | | font-size: 15px |
| | | } |
| | | |
| | | .components-body:hover { |
| | | border: 1px dashed #787be8; |
| | | color : #787be8 |
| | | } |
| | | |
| | | .components-body:hover .svg-icon { |
| | | color: #787be8 |
| | | } |
| | | |
| | | .ghost { |
| | | border : 1px dashed #e06c1d; |
| | | outline-width: 0; |
| | | height : 39px; |
| | | box-sizing : border-box; |
| | | content : ''; |
| | | padding : 0; |
| | | } |
| | | .ghost div { |
| | | color:#fff; |
| | | } |
| | | |
| | | |
| | | .layui-body .active { |
| | | outline : 2px solid #409EFF; |
| | | border : 1px solid #409EFF; |
| | | outline-offset: 0; |
| | | } |
| | | |
| | | #formDesignerForm .layui-form-item { |
| | | position: relative; |
| | | } |
| | | |
| | | #formDesignerForm .grid { |
| | | padding: 5px 5px; |
| | | } |
| | | |
| | | #formDesignerForm .layui-form-item:hover { |
| | | border : 1px solid #409EFF; |
| | | background-color: #e9f4fd !important; |
| | | } |
| | | |
| | | .widget-view-drag { |
| | | position : absolute; |
| | | left : -2px; |
| | | top : -2px; |
| | | bottom : -18px; |
| | | height : 28px; |
| | | line-height: 28px; |
| | | background : #409EFF; |
| | | z-index : 9; |
| | | } |
| | | |
| | | .widget-view-drag i { |
| | | font-size: 14px; |
| | | color : #fff; |
| | | margin : 0 5px; |
| | | cursor : move; |
| | | } |
| | | |
| | | .select-option-drag { |
| | | cursor: move; |
| | | } |
| | | |
| | | .select-option-delete { |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .widget-view-action { |
| | | position : absolute; |
| | | right : 0; |
| | | bottom : 0; |
| | | height : 28px; |
| | | line-height: 28px; |
| | | background : #409EFF; |
| | | z-index : 9; |
| | | } |
| | | |
| | | .widget-view-action i { |
| | | font-size: 14px; |
| | | color : #fff; |
| | | margin : 0 5px; |
| | | cursor : pointer; |
| | | |
| | | } |
| | | |
| | | #formDesignerForm { |
| | | background: #fff; |
| | | border : 1px dashed #999; |
| | | min-height: 94%; |
| | | margin : 10px; |
| | | padding : 10px 10px; |
| | | } |
| | | |
| | | #formDesignerForm .widget-col-list { |
| | | min-height: 50px; |
| | | border : 1px dashed #ccc; |
| | | background: #fff; |
| | | } |
| | | |
| | | #formDesignerForm .widget-slider { |
| | | margin: 18px 10px; |
| | | width : 90%; |
| | | position: absolute!important; |
| | | } |
| | | |
| | | .layui-empty { |
| | | margin : 10px 60px; |
| | | color : #9e9e9e; |
| | | font-size : 16px; |
| | | text-align: center; |
| | | |
| | | } |
| | | |
| | | #columnProperty .layui-form-item.option { |
| | | margin-bottom: 2px; |
| | | } |
| | | |
| | | #columnProperty .layui-form-item.option .layui-inline { |
| | | margin-bottom: 2px; |
| | | } |
| | | |
| | | /* 图片上传 */ |
| | | .uploader-list { |
| | | margin-left: -15px; |
| | | } |
| | | |
| | | .uploader-list .info { |
| | | position : relative; |
| | | margin-top : -25px; |
| | | background-color: black; |
| | | color : white; |
| | | filter : alpha(Opacity=80); |
| | | -moz-opacity : 0.5; |
| | | opacity : 0.5; |
| | | width : 100px; |
| | | height : 25px; |
| | | text-align : center; |
| | | display : none; |
| | | } |
| | | |
| | | .uploader-list .handle { |
| | | position : relative; |
| | | background-color: black; |
| | | color : white; |
| | | filter : alpha(Opacity=80); |
| | | -moz-opacity : 0.5; |
| | | opacity : 0.5; |
| | | width : 100px; |
| | | text-align : right; |
| | | height : 18px; |
| | | margin-bottom : -18px; |
| | | display : none; |
| | | } |
| | | |
| | | .uploader-list .handle i { |
| | | margin-right: 5px; |
| | | } |
| | | |
| | | .uploader-list .handle i:hover { |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .uploader-list .file-iteme { |
| | | margin : 12px 0 0 15px; |
| | | padding: 1px; |
| | | float : left; |
| | | } |
| | | |
| | | |
| | | /*自定义layer颜色*/ |
| | | body .cool-black .layui-layer-title { |
| | | color : #fff; |
| | | height : 50px; |
| | | line-height : 50px; |
| | | background-color: #191a23; |
| | | border : none; |
| | | } |
| | | |
| | | body .cool-black .layui-layer-setwin a { |
| | | color : #fff; |
| | | font-size : 16px; |
| | | font-style : normal; |
| | | font-family : layui-icon !important; |
| | | -webkit-font-smoothing : antialiased; |
| | | -moz-osx-font-smoothing: grayscale; |
| | | } |
| | | |
| | | body .cool-black .layui-layer-btn a { |
| | | background: #333; |
| | | } |
| | | |
| | | |
| | | |
| | | .htmlcodeview, |
| | | .importjsoncodeview { |
| | | position: relative; |
| | | display : none; |
| | | } |
| | | |
| | | .htmlcodeview textarea, |
| | | .getFormData textarea, |
| | | .importjsoncodeview textarea { |
| | | display : block; |
| | | width : 760px; |
| | | height : 560px; |
| | | border : 10px solid #F8F8F8; |
| | | border-top-width: 0; |
| | | padding : 10px; |
| | | line-height : 20px; |
| | | overflow : auto; |
| | | background-color: #3F3F3F; |
| | | color : #eee; |
| | | font-size : 12px; |
| | | font-family : Courier New; |
| | | } |
| | | |
| | | .htmlcodeview a, |
| | | .importjsoncodeview a { |
| | | position: absolute; |
| | | right : 20px; |
| | | bottom : 20px; |
| | | } |
| | | |
| | | .htmlcodeview, |
| | | .importjsoncodedataview { |
| | | position: relative; |
| | | display : none; |
| | | } |
| | | |
| | | .htmlcodeview textarea, |
| | | .getFormData textarea, |
| | | .importjsoncodedataview textarea { |
| | | display : block; |
| | | width : 760px; |
| | | height : 560px; |
| | | border : 10px solid #F8F8F8; |
| | | border-top-width: 0; |
| | | padding : 10px; |
| | | line-height : 20px; |
| | | overflow : auto; |
| | | background-color: #3F3F3F; |
| | | color : #eee; |
| | | font-size : 12px; |
| | | font-family : Courier New; |
| | | } |
| | | |
| | | .htmlcodeview a, |
| | | .importjsoncodedataview a { |
| | | position: absolute; |
| | | right : 20px; |
| | | bottom : 20px; |
| | | } |
| | | |
| | | .aboutusview .about { |
| | | display : block; |
| | | width : 760px; |
| | | height : 554px; |
| | | padding : 20px 20px; |
| | | overflow : hidden; |
| | | background-color: #191a23; |
| | | color : #ccc; |
| | | } |
| | | .aboutusview .about p{ |
| | | line-height: 30px; |
| | | |
| | | } |
| | | |
| | | .aboutusview .about .yellow{ |
| | | color:#e6ec8d; |
| | | } |
| | | |
| | | .layui-disabled { |
| | | background-color: #f5f7fa; |
| | | border-color: #dfe4ed; |
| | | color: #c0c4cc; |
| | | } |
| | | |
| | | .custom-lg{ |
| | | margin: -3px 0px 0px 10px; |
| | | } |
| | | .custom-zc{ |
| | | margin: 0px 0px 0px 10px; |
| | | } |
| | | .custom-sm{ |
| | | margin: 5px 0px 0px 10px; |
| | | } |
| | | .custom-xs{ |
| | | margin: 10px 0px 0px 10px; |
| | | } |
| | | |
| | | .iceEditor-disabled { |
| | | position: absolute; |
| | | width: 100%; |
| | | height: 100%; |
| | | top: 0; |
| | | left: 0; |
| | | background-color: rgba(245,247,250,0.79) !important; |
| | | border-color: #dfe4ed !important; |
| | | color: #c0c4cc !important; |
| | | z-index: 1 !important; |
| | | display: block; |
| | | } |
| | | |
| | | ::-webkit-scrollbar { |
| | | width: 5px; |
| | | color: #000; |
| | | } |
| | | |
| | | .component-group ol { |
| | | display: inline-block; |
| | | background: #fff; |
| | | color: #000; |
| | | min-width: 70px; |
| | | width: 32%; |
| | | height: 70px; |
| | | line-height: 1; |
| | | text-align: center; |
| | | transition: all .2s ease; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .component-group ol:hover { |
| | | background: #009688; |
| | | border-radius: 5px; |
| | | color: #fff; |
| | | border-color: #fff; |
| | | } |
| | | |
| | | |
| | | .component-group ol .icon { |
| | | padding: 10px 5px 12px; |
| | | display: inline-block; |
| | | } |
| | | |
| | | .component-group ol .icon i { |
| | | font-size: 18px; |
| | | } |
| | | |
| | | .layui-icon-switch { |
| | | border: 1px solid #666; |
| | | border-radius: 20px; |
| | | display: inline-block; |
| | | width: 20px; |
| | | height: 10px; |
| | | position: relative; |
| | | } |
| | | |
| | | .layui-icon-switch k { |
| | | position: absolute; |
| | | left: 4px; |
| | | top: 2px; |
| | | width: 6px; |
| | | height: 6px; |
| | | border-radius: 20px; |
| | | background-color: #666; |
| | | -webkit-transition: .1s linear; |
| | | transition: .1s linear; |
| | | } |
| | | |
| | | .component { |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .component-group ol:hover .layui-icon-switch { |
| | | color: #fff; |
| | | border-color: #fff; |
| | | } |
| | | |
| | | .component-group ol:hover k { |
| | | background-color: #fff; |
| | | } |
| | | |
| | | .component-group ol .name { |
| | | font-size: 12px; |
| | | } |
| | | |
| | | .layui-col-md2,.layui-col-md8 { |
| | | border-right: 1px solid #f6f6ff; |
| | | } |
| | | |
| | | .fr { |
| | | float: right; |
| | | } |
| | | |
| | | |
| | | .layui-form-footer { |
| | | position: fixed; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | background-color: #fff; |
| | | box-shadow: 0 -1px 5px rgba(0,0,0,.15); |
| | | padding: 15px; |
| | | z-index: 9999; |
| | | margin-bottom: 0px; |
| | | margin-top: 10px; |
| | | text-align: center; |
| | | } |
| | | .layui-inlioc { |
| | | clear: both; |
| | | } |
| | | |
| | | .layui-fluid { |
| | | padding-top: 20px; |
| | | } |
| | | |
| | | #layui-form-attribute .layui-input-inline { |
| | | width: 169px; |
| | | margin-right: 0; |
| | | } |
| | | |
| | | #layui-form-attribute .layui-form-label { |
| | | padding: 6px; |
| | | padding-right: 10px; |
| | | width: 60px!important; |
| | | } |
| | | |
| | | .layui-minmax { |
| | | width: 76px; |
| | | display: inline-block; |
| | | } |
| | | |
| | | .layui-input-inline em { |
| | | margin: 0px 5px; |
| | | } |
| | | |
| | | .layui-component-tools { |
| | | position: absolute; |
| | | background: #009688; |
| | | right: 0; |
| | | bottom: 0; |
| | | padding: 1px 5px; |
| | | cursor: pointer; |
| | | z-index: 21; |
| | | color: #fff; |
| | | width: 32px; |
| | | height: 20px; |
| | | line-height: 20px; |
| | | text-align: center; |
| | | display: none; |
| | | } |
| | | .layui-input-none { |
| | | display: none; |
| | | } |
| | | |
| | | .layui-component-tools i,.layui-component-move i { |
| | | font-size: 12px; |
| | | } |
| | | |
| | | #layui-elem-field legend { |
| | | margin-left: 39%; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | |
| | | #tab-options input { |
| | | width: 139px; |
| | | display: inline-block; |
| | | margin: 0px 8px; |
| | | } |
| | | |
| | | #form-options .layui-add-option,#tab-options .layui-add-tab { |
| | | position: relative; |
| | | left: 26px; |
| | | } |
| | | |
| | | .layui-slider { |
| | | margin-top: 3px; |
| | | } |
| | | |
| | | #Propertie .layui-slider { |
| | | margin-top: 13px; |
| | | } |
| | | |
| | | #tpl_main,#tpl_right_main { |
| | | margin: 25% auto; |
| | | text-align: center; |
| | | font-size: 18px; |
| | | color: #c9e0f3; |
| | | } |
| | | |
| | | #layui-form-template .item-list { |
| | | padding: 8px 0px; |
| | | } |
| | | |
| | | .item-body { |
| | | border: 1px solid #f6f6f6; |
| | | padding: 20px; |
| | | border-radius: 5px; |
| | | cursor: pointer; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .item-body:hover { |
| | | border: 1px solid #009688; |
| | | } |
| | | |
| | | .item-body .item-img { |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .item-body .item-img img { |
| | | width: 100%;; |
| | | } |
| | | |
| | | .item-body .item-desc { |
| | | margin-top: 10px; |
| | | } |
| | | |
| | | .item-body .item-desc span.item-title{ |
| | | font-size: 13px; |
| | | font-weight: 700; |
| | | } |
| | | .right-button { |
| | | float: right; |
| | | padding: 1px 3px; |
| | | border: none; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .button--text { |
| | | color: #009688; |
| | | background: 0 0; |
| | | padding-left: 0; |
| | | padding-right: 0; |
| | | font-size: 10px; |
| | | } |
| | | |
| | | .layui-htmlview { |
| | | position: relative; |
| | | } |
| | | |
| | | .layui-htmlview textarea { |
| | | display: block; |
| | | width: 760px; |
| | | height: 566px; |
| | | border: 10px solid #F8F8F8; |
| | | border-top-width: 0; |
| | | padding: 10px; |
| | | line-height: 20px; |
| | | overflow: auto; |
| | | background-color: #3F3F3F; |
| | | color: #eee; |
| | | font-size: 12px; |
| | | font-family: Courier New; |
| | | } |
| | | |
| | | .layui-htmlview .layui-htmlbtn{ |
| | | position: absolute; |
| | | right: 20px; |
| | | bottom:20px; |
| | | } |
| | | |
| | | #parse-table .layui-input { |
| | | height: 30px; |
| | | width: 139px; |
| | | font-size: 12px; |
| | | border: none; |
| | | } |
| | | |
| | | |
| | | .components-draggable ol { |
| | | display: inline-block; |
| | | background: #fff; |
| | | color: #000; |
| | | min-width: 70px; |
| | | width: 32%; |
| | | height: 70px; |
| | | line-height: 1; |
| | | text-align: center; |
| | | transition: all .2s ease; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .components-draggable ol:hover { |
| | | background: #009688; |
| | | border-radius: 5px; |
| | | color: #fff; |
| | | border-color: #fff; |
| | | } |
| | | |
| | | |
| | | .components-draggable ol .icon { |
| | | padding: 10px 5px 12px; |
| | | display: inline-block; |
| | | } |
| | | |
| | | .components-draggable ol .icon i { |
| | | font-size: 18px; |
| | | } |
| | | #formPreviewForm .widget-slider { |
| | | margin: 18px 10px; |
| | | width : 90%; |
| | | position: absolute!important; |
| | | } |
| | | .custom-lg{ |
| | | margin: -3px 0px 0px 10px; |
| | | } |
| | | .custom-zc{ |
| | | margin: 0px 0px 0px 10px; |
| | | } |
| | | .custom-sm{ |
| | | margin: 5px 0px 0px 10px; |
| | | } |
| | | .custom-xs{ |
| | | margin: 10px 0px 0px 10px; |
| | | } |
| | | .my-disabled{ |
| | | position: absolute; |
| | | width: 100%; |
| | | height: 100%; |
| | | top: 0; |
| | | left: 0; |
| | | background: rgba(191,191,191,.79); |
| | | } |
| | | .iceEditor-disabled { |
| | | position: absolute; |
| | | width: 100%; |
| | | height: 100%; |
| | | top: 0; |
| | | left: 0; |
| | | background-color: rgba(245,247,250,0.79) !important; |
| | | border-color: #dfe4ed !important; |
| | | color: #c0c4cc !important; |
| | | z-index: 1 !important; |
| | | display: block; |
| | | } |
| | | /* 图片上传 */ |
| | | .uploader-list { |
| | | margin-left: -15px; |
| | | } |
| | | .uploader-list .info { |
| | | position: relative; |
| | | margin-top: -25px; |
| | | background-color: black; |
| | | color: white; |
| | | filter: alpha(Opacity=80); |
| | | -moz-opacity: 0.5; |
| | | opacity: 0.5; |
| | | width: 100px; |
| | | height: 25px; |
| | | text-align: center; |
| | | display: none; |
| | | } |
| | | .uploader-list .handle { |
| | | position: relative; |
| | | background-color: black; |
| | | color: white; |
| | | filter: alpha(Opacity=80); |
| | | -moz-opacity: 0.5; |
| | | opacity: 0.5; |
| | | width: 100px; |
| | | text-align: right; |
| | | height: 18px; |
| | | margin-bottom: -18px; |
| | | display: none; |
| | | } |
| | | .uploader-list .handle i { |
| | | margin-right: 5px; |
| | | } |
| | | .uploader-list .handle i:hover { |
| | | cursor: pointer; |
| | | } |
| | | .uploader-list .file-iteme { |
| | | margin: 12px 0 0 15px; |
| | | padding: 1px; |
| | | float: left; |
| | | } |
New file |
| | |
| | | .none-transition{ |
| | | transition: none; |
| | | -webkit-transition: none; |
| | | } |
New file |
| | |
| | | layui.define(['layer'], function (exports) { |
| | | |
| | | var formField = { |
| | | components : { |
| | | input: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "单行文本", |
| | | tag: "input", |
| | | tagIcon: 'input', |
| | | placeholder: "请输入", |
| | | defaultValue: null, |
| | | labelWidth: 110, |
| | | width:"100%", |
| | | clearable: true, |
| | | maxlength: null, |
| | | showWordLimit: false, |
| | | readonly: false, |
| | | disabled: false, |
| | | required: true, |
| | | hideLabel:false, |
| | | expression:"", |
| | | document: '', |
| | | }, |
| | | password: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "密码框", |
| | | tag: "password", |
| | | tagIcon: 'password', |
| | | placeholder: "请输入", |
| | | defaultValue: null, |
| | | labelWidth: 110, |
| | | width:"100%", |
| | | clearable: true, |
| | | maxlength: null, |
| | | showWordLimit: false, |
| | | readonly: false, |
| | | disabled: false, |
| | | required: true, |
| | | hideLabel:false, |
| | | document: '' |
| | | }, |
| | | select: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "下拉框", |
| | | tag: "select", |
| | | tagIcon: 'select', |
| | | labelWidth: 110, |
| | | width:"100%", |
| | | disabled: false, |
| | | required: true, |
| | | hideLabel:false, |
| | | document: '', |
| | | datasourceType: 'local', |
| | | remoteUrl: 'http://', |
| | | remoteMethod: 'post', |
| | | remoteOptionText:'options.data.dictName',//映射到text |
| | | remoteOptionValue:'options.data.dictId',//映射到value text和value可以是一样的 |
| | | remoteDefaultValue:'12',//表示对应的remoteOptionValue的值 |
| | | options: [ |
| | | { |
| | | text: 'option1', |
| | | value: 'value1', |
| | | checked: true, |
| | | }, |
| | | { |
| | | text: 'option2', |
| | | value: 'value2', |
| | | checked: false, |
| | | }, |
| | | { |
| | | text: 'option3', |
| | | value: 'value3', |
| | | checked: false, |
| | | }, |
| | | ] |
| | | }, |
| | | radio: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "单选组", |
| | | tag: "radio", |
| | | tagIcon: 'radio', |
| | | labelWidth: 110, |
| | | disabled: false, |
| | | hideLabel:false, |
| | | document: '', |
| | | datasourceType: 'local', |
| | | remoteUrl: 'http://', |
| | | remoteMethod: 'post', |
| | | remoteOptionText:'options.data.dictName',//映射到text |
| | | remoteOptionValue:'options.data.dictId',//映射到value text和value可以是一样的 |
| | | options: [ |
| | | { |
| | | text: 'option1', |
| | | value: 'value1', |
| | | checked: true, |
| | | }, |
| | | { |
| | | text: 'option2', |
| | | value: 'value2', |
| | | checked: false, |
| | | }, |
| | | { |
| | | text: 'option3', |
| | | value: 'value3', |
| | | checked: false, |
| | | }, |
| | | ] |
| | | }, |
| | | checkbox: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "复选组", |
| | | tag: "checkbox", |
| | | tagIcon: 'checkbox', |
| | | labelWidth: 110, |
| | | disabled: false, |
| | | required: true, |
| | | hideLabel:false, |
| | | document: '', |
| | | datasourceType: 'local', |
| | | remoteUrl: 'http://', |
| | | remoteMethod: 'post', |
| | | remoteOptionText:'options.data.dictName',//映射到text |
| | | remoteOptionValue:'options.data.dictId',//映射到value text和value可以是一样的 |
| | | options: [ |
| | | { |
| | | text: 'option1', |
| | | value: 'value1', |
| | | checked: true, |
| | | }, |
| | | { |
| | | text: 'option2', |
| | | value: 'value2', |
| | | checked: true, |
| | | }, |
| | | { |
| | | text: 'option3', |
| | | value: 'value3', |
| | | checked: false, |
| | | }, |
| | | ] |
| | | }, |
| | | switch: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "开关", |
| | | tag: "switch", |
| | | tagIcon: 'switch', |
| | | labelWidth: 110, |
| | | width:"100%", |
| | | switchValue: false, |
| | | showWordLimit: false, |
| | | disabled: false, |
| | | hideLabel:false, |
| | | document: '', |
| | | }, |
| | | slider: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "滑块", |
| | | tag: "slider", |
| | | tagIcon: 'slider', |
| | | labelWidth: 110, |
| | | width:"100%", |
| | | defaultValue: 10, |
| | | maxValue: 100, |
| | | minValue: 1, |
| | | stepValue: 2, |
| | | isInput:true, |
| | | disabled: false, |
| | | hideLabel:false, |
| | | document: '', |
| | | }, |
| | | numberInput: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "排序文本框", |
| | | tag: "numberInput", |
| | | tagIcon: 'numberInput', |
| | | labelWidth: 110, |
| | | width:"100%", |
| | | defaultValue: 0, |
| | | maxValue: 100, |
| | | minValue: 0, |
| | | stepValue: 1, |
| | | disabled: false, |
| | | hideLabel:false, |
| | | document: '', |
| | | }, |
| | | labelGeneration: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "标签组件", |
| | | tag: "labelGeneration", |
| | | tagIcon: 'labelGeneration', |
| | | labelWidth: 110, |
| | | width:"100%", |
| | | isEnter: false, |
| | | disabled: false, |
| | | document: '', |
| | | }, |
| | | bottom: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "按钮组件", |
| | | tag: "bottom", |
| | | tagIcon: 'bottom', |
| | | labelWidth: 110, |
| | | buttonIcon:"", |
| | | buttonVlaue:"按钮", |
| | | buttonType:"", |
| | | buttonSize:"", |
| | | disabled: false, |
| | | hideLabel:false, |
| | | document: '', |
| | | }, |
| | | sign: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "签名组件", |
| | | tag: "sign", |
| | | tagIcon: 'sign', |
| | | labelWidth: 110, |
| | | buttonVlaue:"手写签名", |
| | | buttonIcon:"", |
| | | data:"", |
| | | disabled: false, |
| | | hideLabel:false, |
| | | document: '', |
| | | }, |
| | | iconPicker: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "图标选择器", |
| | | tag: "iconPicker", |
| | | tagIcon: 'iconPicker', |
| | | labelWidth: 110, |
| | | defaultValue: '', |
| | | iconPickerSearch: true, |
| | | iconPickerPage: true, |
| | | iconPickerLimit: 12, |
| | | iconPickerCellWidth: '43px', |
| | | disabled: false, |
| | | hideLabel:false, |
| | | document: '', |
| | | }, |
| | | cron: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "Cron表达式", |
| | | tag: "cron", |
| | | tagIcon: 'cron', |
| | | placeholder: "请输入cron表达式,如:0 0 12 * * ?", |
| | | labelWidth: 110, |
| | | width:"100%", |
| | | defaultValue: '* * * * * ?', |
| | | cronUrl: '', |
| | | disabled: false, |
| | | required: true, |
| | | hideLabel:false, |
| | | document: '', |
| | | }, |
| | | date: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "日期", |
| | | tag: "date", |
| | | tagIcon: 'date', |
| | | labelWidth: 110, |
| | | width:"100%", |
| | | clearable: true, |
| | | maxlength: null, |
| | | dateDefaultValue: '2021-05-25', |
| | | dateType: "date",//year month date time datetime |
| | | range: false, |
| | | dateFormat: "yyyy-MM-dd", |
| | | isInitValue: false, |
| | | dataMaxValue: "2088-12-31", |
| | | dataMinValue: "1900-01-01", |
| | | trigger: null,//自定义弹出控件的事件 |
| | | position: "absolute",//fixed,static,abolute |
| | | theme: "default", |
| | | mark: null,//每年的日期 {'0-9-18': '国耻'} 0 即代表每一年 |
| | | showBottom: true, |
| | | zindex:66666666, |
| | | disabled: false, |
| | | required: true, |
| | | hideLabel:false, |
| | | document: '', |
| | | }, |
| | | dateRange: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "日期范围", |
| | | tag: "dateRange", |
| | | tagIcon: 'dateRange', |
| | | labelWidth: 110, |
| | | //width:"100%", |
| | | dateRangeDefaultValue: "2021-06-19 - 2021-07-17", |
| | | clearable: true, |
| | | maxlength: null, |
| | | dateType: "date",//year month date time datetime |
| | | dateFormat: "yyyy-MM-dd", |
| | | isInitValue: true, |
| | | dataMaxValue: "2088-12-31", |
| | | dataMinValue: "1900-01-01", |
| | | trigger: null,//自定义弹出控件的事件 |
| | | position: "absolute",//fixed,static,abolute |
| | | theme: "default", |
| | | mark: null,//每年的日期 {'0-9-18': '国耻'} 0 即代表每一年 |
| | | showBottom: true, |
| | | zindex:66666666, |
| | | disabled: false, |
| | | required: true, |
| | | hideLabel:false, |
| | | document: '', |
| | | }, |
| | | rate: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "评分", |
| | | tag: "rate", |
| | | tagIcon: 'rate', |
| | | labelWidth: 110, |
| | | defaultValue: 0, |
| | | rateLength: 5,//星星长度 |
| | | half: false, |
| | | text: false, |
| | | theme: "default", |
| | | colorSelection:"#ffb800", |
| | | showBottom: true, |
| | | readonly: false, |
| | | hideLabel:false, |
| | | document: '', |
| | | }, |
| | | carousel: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "轮播图", |
| | | tag: "carousel", |
| | | tagIcon: 'carousel', |
| | | width: "100%", |
| | | height: "500px", |
| | | full: false,//是否全屏 |
| | | anim: "default", //轮播切换动画方式, |
| | | interval: 3000,//切换时间 毫秒 |
| | | startIndex: 0,//初始索引 |
| | | arrow: "hover",//切换箭头默认显示状态 |
| | | autoplay: true,//是否自动切换 |
| | | document: '', |
| | | datasourceType: 'local', |
| | | remoteUrl: 'http://', |
| | | remoteMethod: 'post', |
| | | remoteOptionText:'options.data.dictName',//映射到text |
| | | remoteOptionValue:'options.data.dictId',//映射到value text和value可以是一样的 |
| | | options: [ |
| | | { |
| | | text: 'banner1', |
| | | value: './ayq/images/banner1.PNG', |
| | | checked: true, |
| | | }, |
| | | { |
| | | text: 'banner2', |
| | | value: './ayq/images/banner2.PNG', |
| | | checked: false, |
| | | }, |
| | | { |
| | | text: 'banner3', |
| | | value: './ayq/images/banner3.PNG', |
| | | checked: false, |
| | | }, |
| | | ] |
| | | }, |
| | | colorpicker: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "颜色选择器", |
| | | tag: "colorpicker", |
| | | tagIcon: 'colorpicker', |
| | | labelWidth: 110, |
| | | defaultValue: 'rgba(0, 0, 0, 1)', |
| | | colorformat: "#fff", |
| | | alpha: false, |
| | | colors: [], |
| | | size: "", |
| | | showBottom: true, |
| | | disabled: false, |
| | | hideLabel:false, |
| | | document: '', |
| | | }, |
| | | image: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "上传图片", |
| | | tag: "image", |
| | | tagIcon: 'image', |
| | | placeholder: "请输入", |
| | | defaultValue: null, |
| | | labelWidth: null, |
| | | disabled: false, |
| | | required: true, |
| | | document: '', |
| | | uploadUrl: '', |
| | | }, |
| | | file: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "上传文件", |
| | | tag: "file", |
| | | tagIcon: 'file', |
| | | placeholder: "请输入", |
| | | defaultValue: null, |
| | | labelWidth: null, |
| | | disabled: false, |
| | | required: true, |
| | | document: '', |
| | | uploadUrl: '', |
| | | }, |
| | | textarea: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "多行文本", |
| | | tag: "textarea", |
| | | tagIcon: 'textarea', |
| | | placeholder: "请输入", |
| | | defaultValue: null, |
| | | width:"100%", |
| | | readonly: false, |
| | | disabled: false,//这里就是readonly的医生 |
| | | required: true, |
| | | hideLabel:false, |
| | | document: '' |
| | | }, |
| | | editor: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "编辑器", |
| | | tag: "editor", |
| | | tagIcon: 'editor', |
| | | width:"100%", |
| | | clearable: true, |
| | | maxlength: null, |
| | | showWordLimit: false, |
| | | menu: ['backColor', 'fontSize', 'foreColor', 'bold', 'italic', 'underline', 'strikeThrough', 'justifyLeft', 'justifyCenter', 'justifyRight', 'indent', 'outdent', 'insertOrderedList', 'insertUnorderedList', 'superscript', 'subscript', 'createLink', 'unlink', 'hr', 'face','table', 'files', 'music', 'video', 'insertImage', 'removeFormat', 'code', 'line'], |
| | | height: "200px", |
| | | uploadUrl: '/upload/', |
| | | disabled:false, |
| | | hideLabel:false, |
| | | defaultValue:'', |
| | | document: '' |
| | | }, |
| | | blockquote: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "便签信息", |
| | | tag: "blockquote", |
| | | tagIcon: 'blockquote', |
| | | defaultValue: "便签信息", |
| | | width:"100%", |
| | | colorSelection:"#5fb878", |
| | | document: '' |
| | | }, |
| | | line: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "分割线", |
| | | tag: "line", |
| | | tagIcon: 'line', |
| | | defaultValue: "分割线", |
| | | width:"100%", |
| | | colorSelection:"#5fb878", |
| | | document: '' |
| | | }, |
| | | spacing: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "间距", |
| | | tag: "spacing", |
| | | tagIcon: 'spacing', |
| | | defaultValue: "间距", |
| | | whiteSpace:"30", |
| | | document: '' |
| | | }, |
| | | textField: { |
| | | id:'-1', |
| | | index:'-1', |
| | | label: "HTML", |
| | | tag: "textField", |
| | | tagIcon: 'textField', |
| | | defaultValue: "HTML", |
| | | document: '' |
| | | }, |
| | | grid:{ |
| | | id:'-1', |
| | | index:'-1', |
| | | tag: 'grid', |
| | | span: 2, |
| | | columns: [ |
| | | { |
| | | span: 12, |
| | | list: [], |
| | | }, |
| | | { |
| | | span: 12, |
| | | list: [], |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | componentsLang : [ |
| | | { |
| | | component : "c1", |
| | | name:"输入型组件(基于layui)", |
| | | list:[ |
| | | {"key":"input","icon":"layui-icon layui-icon-layer"}, |
| | | {"key":"password","icon":"layui-icon layui-icon-auz"}, |
| | | {"key":"textarea","icon":"layui-icon layui-icon-list"} |
| | | ] |
| | | }, |
| | | { |
| | | component : "c2", |
| | | name:"选择型组件(基于layui)", |
| | | list:[ |
| | | {"key":"select","icon":"layui-icon layui-icon-align-left"}, |
| | | {"key":"radio","icon":"layui-icon layui-icon-radio"}, |
| | | {"key":"checkbox","icon":"layui-icon layui-icon-list"}, |
| | | {"key":"switch","icon":"layui-icon layui-icon-key"}, |
| | | {"key":"slider","icon":"layui-icon layui-icon-slider"}, |
| | | {"key":"date","icon":"layui-icon layui-icon-time"}, |
| | | {"key":"rate","icon":"layui-icon layui-icon-rate-solid"}, |
| | | {"key":"carousel","icon":"layui-icon layui-icon-carousel"}, |
| | | {"key":"colorpicker","icon":"layui-icon layui-icon-theme"}, |
| | | {"key":"image","icon":"layui-icon layui-icon-picture"}, |
| | | {"key":"file","icon":"layui-icon layui-icon-export"}, |
| | | {"key":"dateRange","icon":"layui-icon layui-icon-date"} |
| | | ] |
| | | }, |
| | | { |
| | | component : "c3", |
| | | name:"布局型组件(基于layui)", |
| | | list:[ |
| | | {"key":"grid","icon":"layui-icon layui-icon-layer"}, |
| | | {"key":"blockquote","icon":"layui-icon layui-icon-note"}, |
| | | {"key":"line","icon":"layui-icon layui-icon-subtraction"}, |
| | | {"key":"spacing","icon":"layui-icon layui-icon-more-vertical"}, |
| | | {"key":"bottom","icon":"layui-icon layui-icon-prev-circle"} |
| | | ] |
| | | }, |
| | | { |
| | | component : "c4", |
| | | name:"扩展组件(基于layui)", |
| | | list:[ |
| | | {"key":"numberInput","icon":"layui-icon layui-icon-top"}, |
| | | {"key":"iconPicker","icon":"layui-icon layui-icon-auz"}, |
| | | {"key":"cron","icon":"layui-icon layui-icon-survey"}, |
| | | //{"key":"labelGeneration","icon":"layui-icon layui-icon-auz"}, |
| | | {"key":"sign","icon":"layui-icon layui-icon-layer"} |
| | | ] |
| | | }, |
| | | { |
| | | component : "c5", |
| | | name:"扩展组件(外部)", |
| | | list:[ |
| | | {"key":"editor","icon":"layui-icon layui-icon-layer"} |
| | | ] |
| | | } |
| | | ], |
| | | } |
| | | exports('formField', formField); |
| | | |
| | | }); |
New file |
| | |
| | | /** |
| | | * Layui图标选择器 |
| | | * @author wujiawei0926@yeah.net |
| | | * @version 1.1 |
| | | */ |
| | | |
| | | layui.define(['laypage', 'form'], function (exports) { |
| | | "use strict"; |
| | | |
| | | var IconPicker =function () { |
| | | this.v = '1.1'; |
| | | }, _MOD = 'iconPicker', |
| | | _this = this, |
| | | $ = layui.jquery, |
| | | laypage = layui.laypage, |
| | | form = layui.form, |
| | | BODY = 'body', |
| | | TIPS = '请选择图标'; |
| | | |
| | | /** |
| | | * 渲染组件 |
| | | */ |
| | | IconPicker.prototype.render = function(options){ |
| | | var opts = options, |
| | | // DOM选择器 |
| | | elem = opts.elem, |
| | | // 数据类型:fontClass/unicode |
| | | type = opts.type == null ? 'fontClass' : opts.type, |
| | | // 是否分页:true/false |
| | | page = opts.page == null ? true : opts.page, |
| | | // 每页显示数量 |
| | | limit = opts.limit == null ? 12 : opts.limit, |
| | | // 是否开启搜索:true/false |
| | | search = opts.search == null ? true : opts.search, |
| | | // 每个图标格子的宽度:'43px'或'20%' |
| | | cellWidth = opts.cellWidth, |
| | | // 点击回调 |
| | | click = opts.click, |
| | | // 渲染成功后的回调 |
| | | success = opts.success, |
| | | // json数据 |
| | | data = {}, |
| | | // 唯一标识 |
| | | tmp = new Date().getTime(), |
| | | // 是否使用的class数据 |
| | | isFontClass = opts.type === 'fontClass', |
| | | // 初始化时input的值 |
| | | ORIGINAL_ELEM_VALUE = $(elem).val(), |
| | | TITLE = 'layui-select-title', |
| | | TITLE_ID = 'layui-select-title-' + tmp, |
| | | ICON_BODY = 'layui-iconpicker-' + tmp, |
| | | PICKER_BODY = 'layui-iconpicker-body-' + tmp, |
| | | PAGE_ID = 'layui-iconpicker-page-' + tmp, |
| | | LIST_BOX = 'layui-iconpicker-list-box', |
| | | selected = 'layui-form-selected', |
| | | unselect = 'layui-unselect'; |
| | | |
| | | var a = { |
| | | init: function () { |
| | | data = common.getData[type](); |
| | | |
| | | a.hideElem().createSelect().createBody().toggleSelect(); |
| | | a.preventEvent().inputListen(); |
| | | common.loadCss(); |
| | | |
| | | if (success) { |
| | | success(this.successHandle()); |
| | | } |
| | | |
| | | return a; |
| | | }, |
| | | successHandle: function(){ |
| | | var d = { |
| | | options: opts, |
| | | data: data, |
| | | id: tmp, |
| | | elem: $('#' + ICON_BODY) |
| | | }; |
| | | return d; |
| | | }, |
| | | /** |
| | | * 隐藏elem |
| | | */ |
| | | hideElem: function () { |
| | | $(elem).hide(); |
| | | return a; |
| | | }, |
| | | /** |
| | | * 绘制select下拉选择框 |
| | | */ |
| | | createSelect: function () { |
| | | var oriIcon = '<i class="layui-icon">'; |
| | | |
| | | // 默认图标 |
| | | if(ORIGINAL_ELEM_VALUE === '') { |
| | | if(isFontClass) { |
| | | ORIGINAL_ELEM_VALUE = 'layui-icon-circle-dot'; |
| | | } else { |
| | | ORIGINAL_ELEM_VALUE = ''; |
| | | } |
| | | } |
| | | |
| | | if (isFontClass) { |
| | | oriIcon = '<i class="layui-icon '+ ORIGINAL_ELEM_VALUE +'">'; |
| | | } else { |
| | | oriIcon += ORIGINAL_ELEM_VALUE; |
| | | } |
| | | oriIcon += '</i>'; |
| | | |
| | | var selectHtml = '<div class="layui-iconpicker layui-unselect layui-form-select" id="'+ ICON_BODY +'">' + |
| | | '<div class="'+ TITLE +'" id="'+ TITLE_ID +'">' + |
| | | '<div class="layui-iconpicker-item">'+ |
| | | '<span class="layui-iconpicker-icon layui-unselect">' + |
| | | oriIcon + |
| | | '</span>'+ |
| | | '<i class="layui-edge"></i>' + |
| | | '</div>'+ |
| | | '</div>' + |
| | | '<div class="layui-anim layui-anim-upbit" style="">' + |
| | | '123' + |
| | | '</div>'; |
| | | $(elem).after(selectHtml); |
| | | return a; |
| | | }, |
| | | /** |
| | | * 展开/折叠下拉框 |
| | | */ |
| | | toggleSelect: function () { |
| | | var item = '#' + TITLE_ID + ' .layui-iconpicker-item,#' + TITLE_ID + ' .layui-iconpicker-item .layui-edge'; |
| | | a.event('click', item, function (e) { |
| | | var $icon = $('#' + ICON_BODY); |
| | | if ($icon.hasClass(selected)) { |
| | | $icon.removeClass(selected).addClass(unselect); |
| | | } else { |
| | | // 隐藏其他picker |
| | | $('.layui-form-select').removeClass(selected); |
| | | // 显示当前picker |
| | | $icon.addClass(selected).removeClass(unselect); |
| | | } |
| | | e.stopPropagation(); |
| | | }); |
| | | return a; |
| | | }, |
| | | /** |
| | | * 绘制主体部分 |
| | | */ |
| | | createBody: function () { |
| | | // 获取数据 |
| | | var searchHtml = ''; |
| | | |
| | | if (search) { |
| | | searchHtml = '<div class="layui-iconpicker-search">' + |
| | | '<input class="layui-input">' + |
| | | '<i class="layui-icon"></i>' + |
| | | '</div>'; |
| | | } |
| | | |
| | | // 组合dom |
| | | var bodyHtml = '<div class="layui-iconpicker-body" id="'+ PICKER_BODY +'">' + |
| | | searchHtml + |
| | | '<div class="'+ LIST_BOX +'"></div> '+ |
| | | '</div>'; |
| | | $('#' + ICON_BODY).find('.layui-anim').eq(0).html(bodyHtml); |
| | | a.search().createList().check().page(); |
| | | |
| | | return a; |
| | | }, |
| | | /** |
| | | * 绘制图标列表 |
| | | * @param text 模糊查询关键字 |
| | | * @returns {string} |
| | | */ |
| | | createList: function (text) { |
| | | var d = data, |
| | | l = d.length, |
| | | pageHtml = '', |
| | | listHtml = $('<div class="layui-iconpicker-list">')//'<div class="layui-iconpicker-list">'; |
| | | |
| | | // 计算分页数据 |
| | | var _limit = limit, // 每页显示数量 |
| | | _pages = l % _limit === 0 ? l / _limit : parseInt(l / _limit + 1), // 总计多少页 |
| | | _id = PAGE_ID; |
| | | |
| | | // 图标列表 |
| | | var icons = []; |
| | | |
| | | for (var i = 0; i < l; i++) { |
| | | var obj = d[i]; |
| | | |
| | | // 判断是否模糊查询 |
| | | if (text && obj.indexOf(text) === -1) { |
| | | continue; |
| | | } |
| | | |
| | | // 是否自定义格子宽度 |
| | | var style = ''; |
| | | if (cellWidth !== null) { |
| | | style += ' style="width:' + cellWidth + '"'; |
| | | } |
| | | |
| | | // 每个图标dom |
| | | var icon = '<div class="layui-iconpicker-icon-item" title="'+ obj +'" '+ style +'>'; |
| | | if (isFontClass){ |
| | | icon += '<i class="layui-icon '+ obj +'"></i>'; |
| | | } else { |
| | | icon += '<i class="layui-icon">'+ obj.replace('amp;', '') +'</i>'; |
| | | } |
| | | icon += '</div>'; |
| | | |
| | | icons.push(icon); |
| | | } |
| | | |
| | | // 查询出图标后再分页 |
| | | l = icons.length; |
| | | _pages = l % _limit === 0 ? l / _limit : parseInt(l / _limit + 1); |
| | | for (var i = 0; i < _pages; i++) { |
| | | // 按limit分块 |
| | | var lm = $('<div class="layui-iconpicker-icon-limit" id="layui-iconpicker-icon-limit-' + tmp + (i+1) +'">'); |
| | | |
| | | for (var j = i * _limit; j < (i+1) * _limit && j < l; j++) { |
| | | lm.append(icons[j]); |
| | | } |
| | | |
| | | listHtml.append(lm); |
| | | } |
| | | |
| | | // 无数据 |
| | | if (l === 0) { |
| | | listHtml.append('<p class="layui-iconpicker-tips">无数据</p>'); |
| | | } |
| | | |
| | | // 判断是否分页 |
| | | if (page){ |
| | | $('#' + PICKER_BODY).addClass('layui-iconpicker-body-page'); |
| | | pageHtml = '<div class="layui-iconpicker-page" id="'+ PAGE_ID +'">' + |
| | | '<div class="layui-iconpicker-page-count">' + |
| | | '<span id="'+ PAGE_ID +'-current">1</span>/' + |
| | | '<span id="'+ PAGE_ID +'-pages">'+ _pages +'</span>' + |
| | | ' (<span id="'+ PAGE_ID +'-length">'+ l +'</span>)' + |
| | | '</div>' + |
| | | '<div class="layui-iconpicker-page-operate">' + |
| | | '<i class="layui-icon" id="'+ PAGE_ID +'-prev" data-index="0" prev></i> ' + |
| | | '<i class="layui-icon" id="'+ PAGE_ID +'-next" data-index="2" next></i> ' + |
| | | '</div>' + |
| | | '</div>'; |
| | | } |
| | | |
| | | |
| | | $('#' + ICON_BODY).find('.layui-anim').find('.' + LIST_BOX).html('').append(listHtml).append(pageHtml); |
| | | return a; |
| | | }, |
| | | // 阻止Layui的一些默认事件 |
| | | preventEvent: function() { |
| | | var item = '#' + ICON_BODY + ' .layui-anim'; |
| | | a.event('click', item, function (e) { |
| | | e.stopPropagation(); |
| | | }); |
| | | return a; |
| | | }, |
| | | // 分页 |
| | | page: function () { |
| | | var icon = '#' + PAGE_ID + ' .layui-iconpicker-page-operate .layui-icon'; |
| | | |
| | | $(icon).unbind('click'); |
| | | a.event('click', icon, function (e) { |
| | | var elem = e.currentTarget, |
| | | total = parseInt($('#' +PAGE_ID + '-pages').html()), |
| | | isPrev = $(elem).attr('prev') !== undefined, |
| | | // 按钮上标的页码 |
| | | index = parseInt($(elem).attr('data-index')), |
| | | $cur = $('#' +PAGE_ID + '-current'), |
| | | // 点击时正在显示的页码 |
| | | current = parseInt($cur.html()); |
| | | |
| | | // 分页数据 |
| | | if (isPrev && current > 1) { |
| | | current=current-1; |
| | | $(icon + '[prev]').attr('data-index', current); |
| | | } else if (!isPrev && current < total){ |
| | | current=current+1; |
| | | $(icon + '[next]').attr('data-index', current); |
| | | } |
| | | $cur.html(current); |
| | | |
| | | // 图标数据 |
| | | $('#'+ ICON_BODY + ' .layui-iconpicker-icon-limit').hide(); |
| | | $('#layui-iconpicker-icon-limit-' + tmp + current).show(); |
| | | e.stopPropagation(); |
| | | }); |
| | | return a; |
| | | }, |
| | | /** |
| | | * 搜索 |
| | | */ |
| | | search: function () { |
| | | var item = '#' + PICKER_BODY + ' .layui-iconpicker-search .layui-input'; |
| | | a.event('input propertychange', item, function (e) { |
| | | var elem = e.target, |
| | | t = $(elem).val(); |
| | | a.createList(t); |
| | | }); |
| | | return a; |
| | | }, |
| | | /** |
| | | * 点击选中图标 |
| | | */ |
| | | check: function () { |
| | | var item = '#' + PICKER_BODY + ' .layui-iconpicker-icon-item'; |
| | | a.event('click', item, function (e) { |
| | | var el = $(e.currentTarget).find('.layui-icon'), |
| | | icon = ''; |
| | | if (isFontClass) { |
| | | var clsArr = el.attr('class').split(/[\s\n]/), |
| | | cls = clsArr[1], |
| | | icon = cls; |
| | | $('#' + TITLE_ID).find('.layui-iconpicker-item .layui-icon').html('').attr('class', clsArr.join(' ')); |
| | | } else { |
| | | var cls = el.html(), |
| | | icon = cls; |
| | | $('#' + TITLE_ID).find('.layui-iconpicker-item .layui-icon').html(icon); |
| | | } |
| | | |
| | | $('#' + ICON_BODY).removeClass(selected).addClass(unselect); |
| | | $(elem).val(icon).attr('value', icon); |
| | | // 回调 |
| | | if (click) { |
| | | click({ |
| | | icon: icon |
| | | }); |
| | | } |
| | | |
| | | }); |
| | | return a; |
| | | }, |
| | | // 监听原始input数值改变 |
| | | inputListen: function(){ |
| | | var el = $(elem); |
| | | a.event('change', elem, function(){ |
| | | var value = el.val(); |
| | | }) |
| | | // el.change(function(){ |
| | | |
| | | // }); |
| | | return a; |
| | | }, |
| | | event: function (evt, el, fn) { |
| | | $(BODY).on(evt, el, fn); |
| | | } |
| | | }; |
| | | |
| | | var common = { |
| | | /** |
| | | * 加载样式表 |
| | | */ |
| | | loadCss: function () { |
| | | var css = '.layui-iconpicker {max-width: 280px;}.layui-iconpicker .layui-anim{display:none;position:absolute;left:0;top:42px;padding:5px 0;z-index:899;min-width:100%;border:1px solid #d2d2d2;max-height:300px;overflow-y:auto;background-color:#fff;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12);box-sizing:border-box;}.layui-iconpicker-item{border:1px solid #e6e6e6;width:90px;height:38px;border-radius:4px;cursor:pointer;position:relative;}.layui-iconpicker-icon{border-right:1px solid #e6e6e6;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;width:60px;height:100%;float:left;text-align:center;background:#fff;transition:all .3s;}.layui-iconpicker-icon i{line-height:38px;font-size:18px;}.layui-iconpicker-item > .layui-edge{left:70px;}.layui-iconpicker-item:hover{border-color:#D2D2D2!important;}.layui-iconpicker-item:hover .layui-iconpicker-icon{border-color:#D2D2D2!important;}.layui-iconpicker.layui-form-selected .layui-anim{display:block;}.layui-iconpicker-body{padding:6px;}.layui-iconpicker .layui-iconpicker-list{background-color:#fff;border:1px solid #ccc;border-radius:4px;}.layui-iconpicker .layui-iconpicker-icon-item{display:inline-block;width:21.1%;line-height:36px;text-align:center;cursor:pointer;vertical-align:top;height:36px;margin:4px;border:1px solid #ddd;border-radius:2px;transition:300ms;}.layui-iconpicker .layui-iconpicker-icon-item i.layui-icon{font-size:17px;}.layui-iconpicker .layui-iconpicker-icon-item:hover{background-color:#eee;border-color:#ccc;-webkit-box-shadow:0 0 2px #aaa,0 0 2px #fff inset;-moz-box-shadow:0 0 2px #aaa,0 0 2px #fff inset;box-shadow:0 0 2px #aaa,0 0 2px #fff inset;text-shadow:0 0 1px #fff;}.layui-iconpicker-search{position:relative;margin:0 0 6px 0;border:1px solid #e6e6e6;border-radius:2px;transition:300ms;}.layui-iconpicker-search:hover{border-color:#D2D2D2!important;}.layui-iconpicker-search .layui-input{cursor:text;display:inline-block;width:86%;border:none;padding-right:0;margin-top:1px;}.layui-iconpicker-search .layui-icon{position:absolute;top:11px;right:4%;}.layui-iconpicker-tips{text-align:center;padding:8px 0;cursor:not-allowed;}.layui-iconpicker-page{margin-top:6px;margin-bottom:-6px;font-size:12px;padding:0 2px;}.layui-iconpicker-page-count{display:inline-block;}.layui-iconpicker-page-operate{display:inline-block;float:right;cursor:default;}.layui-iconpicker-page-operate .layui-icon{font-size:12px;cursor:pointer;}.layui-iconpicker-body-page .layui-iconpicker-icon-limit{display:none;}.layui-iconpicker-body-page .layui-iconpicker-icon-limit:first-child{display:block;}'; |
| | | var $style = $('head').find('style[iconpicker]'); |
| | | if ($style.length === 0) { |
| | | $('head').append('<style rel="stylesheet" iconpicker>'+css+'</style>'); |
| | | } |
| | | }, |
| | | /** |
| | | * 获取数据 |
| | | */ |
| | | getData: { |
| | | fontClass: function () { |
| | | var arr = ["layui-icon-rate-half","layui-icon-rate","layui-icon-rate-solid","layui-icon-cellphone","layui-icon-vercode","layui-icon-login-wechat","layui-icon-login-qq","layui-icon-login-weibo","layui-icon-password","layui-icon-username","layui-icon-refresh-3","layui-icon-auz","layui-icon-spread-left","layui-icon-shrink-right","layui-icon-snowflake","layui-icon-tips","layui-icon-note","layui-icon-home","layui-icon-senior","layui-icon-refresh","layui-icon-refresh-1","layui-icon-flag","layui-icon-theme","layui-icon-notice","layui-icon-website","layui-icon-console","layui-icon-face-surprised","layui-icon-set","layui-icon-template-1","layui-icon-app","layui-icon-template","layui-icon-praise","layui-icon-tread","layui-icon-male","layui-icon-female","layui-icon-camera","layui-icon-camera-fill","layui-icon-more","layui-icon-more-vertical","layui-icon-rmb","layui-icon-dollar","layui-icon-diamond","layui-icon-fire","layui-icon-return","layui-icon-location","layui-icon-read","layui-icon-survey","layui-icon-face-smile","layui-icon-face-cry","layui-icon-cart-simple","layui-icon-cart","layui-icon-next","layui-icon-prev","layui-icon-upload-drag","layui-icon-upload","layui-icon-download-circle","layui-icon-component","layui-icon-file-b","layui-icon-user","layui-icon-find-fill","layui-icon-loading","layui-icon-loading-1","layui-icon-add-1","layui-icon-play","layui-icon-pause","layui-icon-headset","layui-icon-video","layui-icon-voice","layui-icon-speaker","layui-icon-fonts-del","layui-icon-fonts-code","layui-icon-fonts-html","layui-icon-fonts-strong","layui-icon-unlink","layui-icon-picture","layui-icon-link","layui-icon-face-smile-b","layui-icon-align-left","layui-icon-align-right","layui-icon-align-center","layui-icon-fonts-u","layui-icon-fonts-i","layui-icon-tabs","layui-icon-radio","layui-icon-circle","layui-icon-edit","layui-icon-share","layui-icon-delete","layui-icon-form","layui-icon-cellphone-fine","layui-icon-dialogue","layui-icon-fonts-clear","layui-icon-layer","layui-icon-date","layui-icon-water","layui-icon-code-circle","layui-icon-carousel","layui-icon-prev-circle","layui-icon-layouts","layui-icon-util","layui-icon-templeate-1","layui-icon-upload-circle","layui-icon-tree","layui-icon-table","layui-icon-chart","layui-icon-chart-screen","layui-icon-engine","layui-icon-triangle-d","layui-icon-triangle-r","layui-icon-file","layui-icon-set-sm","layui-icon-add-circle","layui-icon-404","layui-icon-about","layui-icon-up","layui-icon-down","layui-icon-left","layui-icon-right","layui-icon-circle-dot","layui-icon-search","layui-icon-set-fill","layui-icon-group","layui-icon-friends","layui-icon-reply-fill","layui-icon-menu-fill","layui-icon-log","layui-icon-picture-fine","layui-icon-face-smile-fine","layui-icon-list","layui-icon-release","layui-icon-ok","layui-icon-help","layui-icon-chat","layui-icon-top","layui-icon-star","layui-icon-star-fill","layui-icon-close-fill","layui-icon-close","layui-icon-ok-circle","layui-icon-add-circle-fine"]; |
| | | return arr; |
| | | }, |
| | | unicode: function () { |
| | | return ["&#xe6c9;","&#xe67b;","&#xe67a;","&#xe678;","&#xe679;","&#xe677;","&#xe676;","&#xe675;","&#xe673;","&#xe66f;","&#xe9aa;","&#xe672;","&#xe66b;","&#xe668;","&#xe6b1;","&#xe702;","&#xe66e;","&#xe68e;","&#xe674;","&#xe669;","&#xe666;","&#xe66c;","&#xe66a;","&#xe667;","&#xe7ae;","&#xe665;","&#xe664;","&#xe716;","&#xe656;","&#xe653;","&#xe663;","&#xe6c6;","&#xe6c5;","&#xe662;","&#xe661;","&#xe660;","&#xe65d;","&#xe65f;","&#xe671;","&#xe65e;","&#xe659;","&#xe735;","&#xe756;","&#xe65c;","&#xe715;","&#xe705;","&#xe6b2;","&#xe6af;","&#xe69c;","&#xe698;","&#xe657;","&#xe65b;","&#xe65a;","&#xe681;","&#xe67c;","&#xe601;","&#xe857;","&#xe655;","&#xe770;","&#xe670;","&#xe63d;","&#xe63e;","&#xe654;","&#xe652;","&#xe651;","&#xe6fc;","&#xe6ed;","&#xe688;","&#xe645;","&#xe64f;","&#xe64e;","&#xe64b;","&#xe62b;","&#xe64d;","&#xe64a;","&#xe64c;","&#xe650;","&#xe649;","&#xe648;","&#xe647;","&#xe646;","&#xe644;","&#xe62a;","&#xe643;","&#xe63f;","&#xe642;","&#xe641;","&#xe640;","&#xe63c;","&#xe63b;","&#xe63a;","&#xe639;","&#xe638;","&#xe637;","&#xe636;","&#xe635;","&#xe634;","&#xe633;","&#xe632;","&#xe631;","&#xe630;","&#xe62f;","&#xe62e;","&#xe62d;","&#xe62c;","&#xe629;","&#xe628;","&#xe625;","&#xe623;","&#xe621;","&#xe620;","&#xe61f;","&#xe61c;","&#xe60b;","&#xe619;","&#xe61a;","&#xe603;","&#xe602;","&#xe617;","&#xe615;","&#xe614;","&#xe613;","&#xe612;","&#xe611;","&#xe60f;","&#xe60e;","&#xe60d;","&#xe60c;","&#xe60a;","&#xe609;","&#xe605;","&#xe607;","&#xe606;","&#xe604;","&#xe600;","&#xe658;","&#x1007;","&#x1006;","&#x1005;","&#xe608;"]; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | a.init(); |
| | | return new IconPicker(); |
| | | }; |
| | | |
| | | /** |
| | | * 选中图标 |
| | | * @param filter lay-filter |
| | | * @param iconName 图标名称,自动识别fontClass/unicode |
| | | */ |
| | | IconPicker.prototype.checkIcon = function (filter, iconName){ |
| | | var el = $('*[lay-filter='+ filter +']'), |
| | | p = el.next().find('.layui-iconpicker-item .layui-icon'), |
| | | c = iconName; |
| | | |
| | | if (c.indexOf('#xe') > 0){ |
| | | p.html(c); |
| | | } else { |
| | | p.html('').attr('class', 'layui-icon ' + c); |
| | | } |
| | | el.attr('value', c).val(c); |
| | | }; |
| | | |
| | | var iconPicker = new IconPicker(); |
| | | exports(_MOD, iconPicker); |
| | | }); |
New file |
| | |
| | | layui.define(['form'], function (exports) { |
| | | |
| | | var form = layui.form, |
| | | $ = layui.jquery, |
| | | layer = layui.layer, |
| | | index = 0, |
| | | oldId, |
| | | MOD_NAME = 'labelGeneration', |
| | | formField = { |
| | | label: { |
| | | id: '-1', |
| | | tag: "label", |
| | | }, |
| | | }, |
| | | labelGeneration = { |
| | | set: function (options) { |
| | | var that = this; |
| | | that.config = $.extend({} |
| | | , that.config |
| | | , options); |
| | | return that; |
| | | } |
| | | //事件监听 |
| | | , on: function (events |
| | | , callback) { |
| | | return layui.onevent.call(this |
| | | , MOD_NAME |
| | | , events |
| | | , callback); |
| | | } |
| | | }, |
| | | Class = function (options) { |
| | | var that = this; |
| | | that.config = $.extend({} |
| | | , that.config |
| | | , labelGeneration.config |
| | | , options); |
| | | that.render(); |
| | | }, |
| | | thisIns = function () { |
| | | var that = this |
| | | , options = that.config; |
| | | return { |
| | | reload: function (options) { |
| | | that.reload.call(that |
| | | , options); |
| | | }, getOptions: function () { |
| | | return options || null; |
| | | }, getData: function () { |
| | | return options.data || null; |
| | | } |
| | | } |
| | | } |
| | | |
| | | Class.prototype.config = { |
| | | version: "1.0.0" |
| | | , Author: "谁家没一个小强" |
| | | , generateId: 0 |
| | | , data: [] |
| | | , isEnter: false |
| | | }; |
| | | |
| | | /* 自动生成ID 当前页面自动排序*/ |
| | | Class.prototype.autoId = function (tag) { |
| | | var that = this, |
| | | options = that.config; |
| | | options.generateId = options.generateId + 1; |
| | | return tag + '_' + options.generateId; |
| | | } |
| | | |
| | | Class.prototype.components = { |
| | | label: { |
| | | render: function (json,options) { |
| | | var _html = '<blockquote class="layui-elem-quote">'; |
| | | _html += '<div class="layui-form layui-form-pane layui-form-item">'; |
| | | _html += '<label class="layui-form-label">输入标签</label>'; |
| | | _html += '<div class="layui-input-inline">'; |
| | | if (options.isEnter) { |
| | | _html += '<input type="text" id="{0}" placeholder="按回车生成标签" autocomplete="off" class="layui-input">' |
| | | .format(json.id); |
| | | } else { |
| | | _html += '<input type="text" id="{0}" placeholder="通过按钮生成标签" autocomplete="off" class="layui-input">' |
| | | .format(json.id); |
| | | } |
| | | _html += '</div>'; |
| | | if (!options.isEnter) { |
| | | _html += '<button type="button" id="{0}-button" class="layui-btn layui-btn-normal">确定</button>'.format(json.id); |
| | | } |
| | | _html += '<label class="layui-form-label">颜色选择</label>'; |
| | | _html += '<div class="layui-input-inline">'; |
| | | _html += '<select lay-filter="{0}-switchTest">'.format(json.id); |
| | | _html += '<option value="" selected>墨绿色</option>'; |
| | | _html += '<option value="layui-btn-primary">原始色</option>'; |
| | | _html += '<option value="layui-btn-normal">天蓝色</option>'; |
| | | _html += '<option value="layui-btn-warm">暖黄色</option>'; |
| | | _html += '<option value="layui-btn-danger">红色</option>'; |
| | | _html += '</select>'; |
| | | _html += '</div>'; |
| | | _html += '</div>'; |
| | | _html += '<div id="{0}-content" class="layui-btn-container"></div>'.format(json.id); |
| | | _html += '</blockquote>'; |
| | | return _html; |
| | | }, |
| | | update: function (json) { |
| | | |
| | | }, |
| | | /* 获取对象 */ |
| | | jsonData: function (id, that) { |
| | | //分配一个新的ID |
| | | var _json = JSON.parse(JSON.stringify(formField.label)); |
| | | _json.id = id == undefined ? that.autoId(_json.tag) : id; |
| | | that.checkId(_json,that); |
| | | return _json; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | /* 判定id是否重复*/ |
| | | Class.prototype.checkId = function (json,that) { |
| | | if ($("#" + json.id + "-content").length != 0) { |
| | | json.id = that.autoId(json.tag); |
| | | that.checkId(json); |
| | | } else { |
| | | return; |
| | | } |
| | | } |
| | | |
| | | Class.prototype.bindGridSortEvent = function (json) { |
| | | var that = this |
| | | , options = that.config; |
| | | var formItemSort = Sortable.create(document.getElementById(json.id + "-content"), { |
| | | group: { |
| | | name: 'group' + json.id |
| | | }, |
| | | animation: 1000, |
| | | onEnd: function (evt) { |
| | | var _values = $("#" + json.id + "-content").find("div"); |
| | | var ops = []; |
| | | for (var i = 0; i < _values.length; i++) { |
| | | ops.push({"ngColor": $(_values[i]).attr("ng-color"), "value": $(_values[i]).text()}); |
| | | } |
| | | options.data = ops; |
| | | } |
| | | }); |
| | | } |
| | | |
| | | /* 绑定事件*/ |
| | | Class.prototype.deleteValue = function (value, ngValue) { |
| | | var that = this |
| | | , options = that.config; |
| | | for (var i = 0; i < options.data.length; i++) { |
| | | if (options.data[i].value === value && options.data[i].ngColor === ngValue) { |
| | | options.data.splice(i, 1); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* 绑定事件*/ |
| | | Class.prototype.bindPropertyEvent = function (_json) { |
| | | var that = this |
| | | , options = that.config; |
| | | var colorClass = ""; |
| | | if (options.isEnter) { |
| | | $("#" + _json.id).keypress(function (event) { |
| | | if (event.which === 13) { |
| | | var _value = $(this).val(); |
| | | if (_value === "") { |
| | | layer.msg('标签值不能为空'); |
| | | return; |
| | | } |
| | | index = index + 1; |
| | | var _html = '<div class="layui-btn {0} none-transition" id="{2}" ng-index="{3}" ng-color="{0}">{1}<i class="layui-icon layui-icon-close"></i></div>' |
| | | .format(colorClass, _value, _json.id + index, index); |
| | | $("#" + _json.id + "-content").append(_html); |
| | | options.data.push({"ngColor": colorClass, "value": _value}); |
| | | $("#" + _json.id + index + " .layui-icon-close").click(function () { |
| | | that.deleteValue($(this).parent().text(), $(this).parent().attr("ng-color")); |
| | | $(this).parent().remove(); |
| | | }); |
| | | return false; |
| | | } |
| | | }); |
| | | } else { |
| | | $("#" + _json.id + "-button").click(function (event) { |
| | | var _value = $("#" + _json.id).val(); |
| | | if (_value === "") { |
| | | layer.msg('标签值不能为空'); |
| | | return; |
| | | } |
| | | index = index + 1; |
| | | var _html = '<div class="layui-btn {0} none-transition" id="{2}" ng-index="{3}" ng-color="{0}">{1}<i class="layui-icon layui-icon-close"></i></div>' |
| | | .format(colorClass, _value, _json.id + index, index); |
| | | $("#" + _json.id + "-content").append(_html); |
| | | options.data.push({"ngColor": colorClass, "value": _value}); |
| | | $("#" + _json.id + index + " .layui-icon-close").click(function () { |
| | | that.deleteValue($(this).parent().text(), $(this).parent().attr("ng-color")); |
| | | $(this).parent().remove(); |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | form.on('select(' + _json.id + '-switchTest)', function (data) { |
| | | colorClass = data.value; |
| | | }); |
| | | for (var i = 0; i < options.data.length; i++) { |
| | | index = index + 1; |
| | | var _html = '<div class="layui-btn {0} none-transition" id="{2}" ng-index="{3}" ng-color="{0}">{1}<i class="layui-icon layui-icon-close"></i></div>' |
| | | .format(options.data[i].ngColor, options.data[i].value, _json.id + index, index); |
| | | $("#" + _json.id + "-content").append(_html); |
| | | $("#" + _json.id + index + " .layui-icon-close").click(function () { |
| | | that.deleteValue($(this).parent().text(), $(this).parent().attr("ng-color")); |
| | | $(this).parent().remove(); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | /* 渲染组件 */ |
| | | Class.prototype.renderComponents = function () { |
| | | var that = this |
| | | , options = that.config; |
| | | var elem = $(options.elem); |
| | | elem.empty(); |
| | | var jsonData = that.components['label'].jsonData(undefined, that); |
| | | elem.append(that.components['label'].render(jsonData,options)); |
| | | that.bindPropertyEvent(jsonData); |
| | | that.bindGridSortEvent(jsonData); |
| | | form.render(); |
| | | } |
| | | |
| | | Class.prototype.reload = function (options) { |
| | | var that = this; |
| | | options = options || {};//如果是空的话,就赋值 {} |
| | | that.config = $.extend({} |
| | | , that.config |
| | | , labelGeneration.config |
| | | , options); |
| | | that.render(options); |
| | | } |
| | | |
| | | //核心入口 初始化一个 regionSelect 类 |
| | | labelGeneration.render = function (options) { |
| | | var ins = new Class(options); |
| | | return thisIns.call(ins); |
| | | } |
| | | /** |
| | | * 渲染组件 |
| | | */ |
| | | Class.prototype.render = function (options) { |
| | | var that = this |
| | | , options = that.config; |
| | | that.renderComponents(); |
| | | } |
| | | |
| | | String.prototype.format = function (args) { |
| | | var result = this; |
| | | if (arguments.length > 0) { |
| | | if (arguments.length == 1 && typeof (args) == "object") { |
| | | for (var key in args) { |
| | | if (args[key] != undefined) { |
| | | var reg = new RegExp("({" + key + "})" |
| | | , "g"); |
| | | result = result.replace(reg |
| | | , args[key]); |
| | | } |
| | | } |
| | | } else { |
| | | for (var i = 0; i < arguments.length; i++) { |
| | | if (arguments[i] != undefined) { |
| | | var reg = new RegExp("({[" + i + "]})" |
| | | , "g"); |
| | | result = result.replace(reg |
| | | , arguments[i]); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | exports(MOD_NAME, labelGeneration); |
| | | }); |
New file |
| | |
| | | layui.define(['jquery','util','layer'],function (exports) { |
| | | var $ = layui.$, |
| | | util = layui.util, |
| | | layer = layui.layer, |
| | | input_elem = 'input[number-input]', |
| | | baseClassName = 'layui-input-number', |
| | | numberInputBtn = [ |
| | | '<div class="layui-number-input-btn">', |
| | | '<i class="layui-icon layui-icon-up" lay-click="numberUp"></i>', |
| | | '<i class="layui-icon layui-icon-down" lay-click="numberDown"></i>', |
| | | '</div>', |
| | | ].join(''), |
| | | style = [ |
| | | '<style type="text/css">', |
| | | '.layui-number-input-container{position:relative;width:100%}', |
| | | '.'+baseClassName+'::-webkit-outer-spin-button,.'+baseClassName+'::-webkit-inner-spin-button{-webkit-appearance: none;}', |
| | | '.'+baseClassName+'{-moz-appearance: textfield;padding-right:22px}', |
| | | '.layui-number-input-btn{position:absolute;top:0;right:0;width:20px;height:100%;}', |
| | | '.layui-number-input-btn i{position:absolute;width:20px;height:50%;bottom:0;font-size:12px;text-align:center;line-height:16px;cursor: pointer;}', |
| | | '.layui-number-input-btn i:first-child{top:0}', |
| | | '.layui-number-input-btn i:hover{background:#eee;}', |
| | | '</style>' |
| | | ].join(''); |
| | | $('head link:last')[0] && $('head link:last').after(style) || $('head').append(style); |
| | | |
| | | var numberInput = { |
| | | options:{ |
| | | elem:input_elem |
| | | }, |
| | | render:function (option) { |
| | | var _this = this; |
| | | _this.options = $.extend(_this.options, option); |
| | | $(_this.options.elem).not('[lay-ignore]').addClass(baseClassName).wrap('<div class="layui-number-input-container"></div>'); |
| | | $(_this.options.elem).not('[lay-ignore]').after(numberInputBtn); |
| | | _this.listen(); |
| | | }, |
| | | listen:function () { |
| | | var _this = this; |
| | | $(_this.options.elem).bind('input propertychange',function () { |
| | | var value = $(this).val(); |
| | | $(this).val(value.replace(/[^\-?\d.]/g,'')); |
| | | }); |
| | | |
| | | $(_this.options.elem).keydown(function (event) { |
| | | var e = event||window.event; |
| | | var k = e.keyCode || e.which; |
| | | switch (k) { |
| | | case 38: |
| | | // 按下向上箭头 |
| | | $(this).siblings('.layui-number-input-btn').children('[lay-click="numberUp"]').trigger('click').css('background','#eee'); |
| | | break; |
| | | case 40: |
| | | // 按下向上箭头 |
| | | $(this).siblings('.layui-number-input-btn').children('[lay-click="numberDown"]').trigger('click').css('background','#eee'); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | return false; |
| | | }); |
| | | $(_this.options.elem).keyup(function () { |
| | | var e = event||window.event; |
| | | var k = e.keyCode || e.which; |
| | | switch (k) { |
| | | case 38: |
| | | // 按下向上箭头 |
| | | $(this).siblings('.layui-number-input-btn').children('[lay-click="numberUp"]').css('background',''); |
| | | break; |
| | | case 40: |
| | | // 按下向上箭头 |
| | | $(this).siblings('.layui-number-input-btn').children('[lay-click="numberDown"]').css('background',''); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | return false; |
| | | }); |
| | | var timeOut; |
| | | //长按 |
| | | $('[lay-click="numberUp"],[lay-click="numberDown"]').mousedown(function () { |
| | | var $this = $(this); |
| | | timeOut = setInterval(function () { |
| | | $this.trigger('click'); |
| | | },200) |
| | | }); |
| | | $('[lay-click="numberUp"],[lay-click="numberDown"]').mouseup(function () { |
| | | clearInterval(timeOut); |
| | | }); |
| | | $('[lay-click="numberUp"],[lay-click="numberDown"]').mouseout(function () { |
| | | clearInterval(timeOut); |
| | | }); |
| | | util.event('lay-click',{ |
| | | numberUp:function (othis) { |
| | | var thisInput = othis.parent().parent().children('.'+baseClassName); |
| | | var thisInputValue = Number(thisInput.val()||0); |
| | | var step = thisInput.attr('step')||1; |
| | | var maxValue = Number(thisInput.attr('max')); |
| | | if (maxValue!=undefined){ |
| | | if (thisInputValue>=maxValue){ |
| | | layer.tips('最大值'+maxValue,thisInput,{tips:1}); |
| | | return false; |
| | | } |
| | | } |
| | | thisInputValue=_this.add(thisInputValue,parseFloat(step)); |
| | | thisInput.val('').focus().val(thisInputValue); |
| | | }, |
| | | numberDown:function(othis){ |
| | | var thisInput = othis.parent().parent().children('.'+baseClassName); |
| | | var thisInputValue = thisInput.val()||0; |
| | | var step = thisInput.attr('step')||1; |
| | | var minValue = thisInput.attr('min'); |
| | | if (minValue!=undefined){ |
| | | if (thisInputValue<=minValue){ |
| | | layer.tips('最小值'+minValue,thisInput,{tips:1}); |
| | | return false; |
| | | } |
| | | } |
| | | thisInputValue = _this.subtraction(thisInputValue,step); |
| | | thisInput.val('').focus().val(thisInputValue); |
| | | } |
| | | }); |
| | | }, |
| | | /** |
| | | * 加法 |
| | | * @param arg1 |
| | | * @param arg2 |
| | | * @returns {number} |
| | | */ |
| | | add:function (arg1, arg2) { |
| | | var r1,r2,m; |
| | | try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0} |
| | | try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0} |
| | | m=Math.pow(10,Math.max(r1,r2)) |
| | | return (this.multiplication(arg1,m)+this.multiplication(arg2,m))/m |
| | | }, |
| | | /** |
| | | * 减法 |
| | | * @param arg1 被减数 |
| | | * @param arg2 减数 |
| | | * @returns {string} |
| | | */ |
| | | subtraction:function (arg1, arg2) { |
| | | var r1, r2, m, n; |
| | | try { |
| | | r1 = arg1.toString().split(".")[1].length; |
| | | } |
| | | catch (e) { |
| | | r1 = 0; |
| | | } |
| | | try { |
| | | r2 = arg2.toString().split(".")[1].length; |
| | | } |
| | | catch (e) { |
| | | r2 = 0; |
| | | } |
| | | m = Math.pow(10, Math.max(r1, r2)); |
| | | //last modify by deeka |
| | | //动态控制精度长度 |
| | | n = (r1 >= r2) ? r1 : r2; |
| | | return ((arg1 * m - arg2 * m) / m).toFixed(n); |
| | | }, |
| | | /** |
| | | * 乘法 |
| | | * @param arg1 |
| | | * @param arg2 |
| | | * @returns {number} |
| | | */ |
| | | multiplication:function (arg1,arg2) { |
| | | var m=0,s1=arg1.toString(),s2=arg2.toString(); |
| | | try{m+=s1.split(".")[1].length}catch(e){} |
| | | try{m+=s2.split(".")[1].length}catch(e){} |
| | | return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m) |
| | | }, |
| | | /** |
| | | * 除法 |
| | | * @param arg1 |
| | | * @param arg2 |
| | | * @returns {*|number} |
| | | */ |
| | | division:function (arg1,arg2) { |
| | | var t1 = 0, t2 = 0, r1, r2; |
| | | try { |
| | | t1 = arg1.toString().split(".")[1].length |
| | | } catch (e) { |
| | | } |
| | | try { |
| | | t2 = arg2.toString().split(".")[1].length |
| | | } catch (e) { |
| | | } |
| | | with (Math) { |
| | | r1 = Number(arg1.toString().replace(".", "")) |
| | | r2 = Number(arg2.toString().replace(".", "")) |
| | | return this.multiplication((r1 / r2), pow(10, t2 - t1)); |
| | | } |
| | | } |
| | | }; |
| | | //外部接口 |
| | | var exportApi = { |
| | | render:function(option){ |
| | | numberInput.render(option) |
| | | }, |
| | | }; |
| | | exports('numberInput',exportApi); |
| | | }); |
New file |
| | |
| | | layui.define(['layer'], function (exports) { |
| | | |
| | | var staticField = { |
| | | lang : { |
| | | id: "标识", |
| | | label: "标题", |
| | | index: "序号", |
| | | tag: "表单类型", |
| | | tagIcon: '图标', |
| | | width: '宽度', |
| | | height: "高度", |
| | | span: '网格宽度', |
| | | placeholder: "placeholder", |
| | | defaultValue: "默认值", |
| | | dateDefaultValue:'默认时间', |
| | | labelWidth: "文本宽度", |
| | | clearable: "是否清楚", |
| | | prepend: "前缀", |
| | | append: "追加", |
| | | prefixIcon: '前缀图标', |
| | | suffixIcon: '后缀图标', |
| | | maxlength: "最大长度", |
| | | showWordLimit: "是否限制字符", |
| | | readonly: "只读", |
| | | disabled: "禁用", |
| | | required: "必填", |
| | | columns: "列数", |
| | | options: "选项", |
| | | switchValue: "默认值", |
| | | maxValue: "最大值", |
| | | minValue: "最小值", |
| | | dataMaxValue: "最大日期", |
| | | dataMinValue: "最小日期", |
| | | stepValue: "步长", |
| | | dateType: "日期类型", |
| | | dateFormat: "日期格式", |
| | | half: "显示半星", |
| | | theme: "皮肤", |
| | | rateLength: "星星个数", |
| | | interval: "间隔毫秒", |
| | | startIndex: "开始位置", |
| | | full: "是否全屏", |
| | | arrow: "鼠标样式", |
| | | contents: "内容", |
| | | document: '帮助文档', |
| | | input: "输入框", |
| | | select: "下拉", |
| | | checkbox: "多选组", |
| | | radio: "单选组", |
| | | date: "日期", |
| | | editor: "iceEditor编辑器", |
| | | slider: "滑块", |
| | | image: "图片", |
| | | grid: "一行多列", |
| | | colorpicker: "颜色选择器", |
| | | textarea: "多行文本", |
| | | rate: "评分控件", |
| | | switch: "开关", |
| | | password: "密码框", |
| | | carousel: "轮播", |
| | | text: "显示文本", |
| | | uploadUrl: "上传路径", |
| | | expression: "验证", |
| | | file: "文件", |
| | | autoplay: "自动切换", |
| | | anim: "切换方式", |
| | | arrow: "切换箭头", |
| | | tab:"tab选项卡", |
| | | tabHeaders:"tab标题", |
| | | isInput:"显示输入框", |
| | | dateRange:"日期范围", |
| | | dateRangeDefaultValue:"默认范围", |
| | | menu:"头部菜单", |
| | | numberInput:"排序文本框", |
| | | iconPicker:"图标选择器", |
| | | iconPickerSearch:"是否搜索", |
| | | iconPickerPage:"是否分页", |
| | | iconPickerLimit:"显示数量", |
| | | iconPickerCellWidth:"图标宽度", |
| | | cron:"Cron表达式", |
| | | cronUrl:"运行路径", |
| | | labelGeneration:"标签组件", |
| | | isEnter:"是否回车", |
| | | buttonIcon:"按钮图标", |
| | | buttonType:"按钮类型", |
| | | buttonSize:"组件尺寸", |
| | | bottom:"按钮组件", |
| | | buttonVlaue:"按钮文字", |
| | | sign:"sign签名组件", |
| | | hideLabel:"隐藏标签", |
| | | colorSelection:"颜色选择", |
| | | blockquote:"便签信息", |
| | | line:"分割线", |
| | | spacing:"间距", |
| | | whiteSpace:"组件高度", |
| | | textField:"HTML" |
| | | }, |
| | | templateFormList : [ |
| | | ], |
| | | expressions : [{text: '默认', value: ""} |
| | | , {text: '数字', value: 'number'} |
| | | , {text: '邮箱', value: 'email'} |
| | | , {text: '手机', value: 'phone'} |
| | | , {text: '身份证', value: 'identity'} |
| | | , {text: '日期', value: 'date'} |
| | | , {text: '网址', value: 'url'} |
| | | , {text: '密码', value: 'pass'} |
| | | ], anims : [{text: '左右切换', value: 'default'} |
| | | , {text: '上下切换', value: 'updown'} |
| | | , {text: '渐隐渐显切换', value: 'fade'} |
| | | ], arrows : [{text: '悬停显示', value: 'hover'} |
| | | , {text: '始终显示', value: 'always'} |
| | | , {text: '始终不显示', value: 'none'}] |
| | | , dateTypes : [{text: '年选择器', value: 'year'} |
| | | , {text: '年月选择器', value: 'month'} |
| | | , {text: '时间选择器', value: 'time'} |
| | | , {text: '日期选择器', value: 'date'} |
| | | , {text: '日期时间选择器', value: 'datetime'}] |
| | | , buttonTypes : [{text: '原始', value: 'layui-btn-primary'} |
| | | , {text: '默认', value: ""} |
| | | , {text: '百搭', value: 'layui-btn-normal'} |
| | | , {text: '暖色', value: 'layui-btn-warm'} |
| | | , {text: '警告', value: ' layui-btn-danger'}] |
| | | , buttonSizes : [{text: '大型', value: 'layui-btn-lg'} |
| | | , {text: '默认', value: ""} |
| | | , {text: '小型', value: 'layui-btn-sm'} |
| | | , {text: '迷你', value: 'layui-btn-xs'}] |
| | | , dateFormats : ["yyyy年MM月", "yyyy-MM-dd", "dd/MM/yyyy", "yyyyMMdd", "yyyy-MM-dd HH:mm:ss", "yyyy年MM月dd日 HH时mm分ss秒"] |
| | | , iceEditMenus : [ |
| | | {value:'backColor',text:'字体背景颜色'},{value:'fontSize',text:'字体大小'},{value:'foreColor',text:'字体颜色'},{value:'bold',text:'粗体'}, |
| | | {value:'italic',text:'斜体'},{value:'underline',text:'下划线'},{value:'strikeThrough',text:'删除线'},{value:'justifyLeft',text:'左对齐'}, |
| | | {value:'justifyCenter',text:'居中对齐'},{value:'justifyRight',text:'右对齐'},{value:'indent',text:'增加缩进'},{value:'outdent',text:'减少缩进'}, |
| | | {value:'insertOrderedList',text:'有序列表'},{value:'insertUnorderedList',text:'无序列表'},{value:'superscript',text:'上标'},{value:'subscript',text:'下标'}, |
| | | {value:'createLink',text:'创建连接'},{value:'unlink',text:'取消连接'},{value:'hr',text:'水平线'},{value:'face',text:'表情'},{value:'table',text:'表格'}, |
| | | {value:'files',text:'附件'},{value:'music',text:'音乐'},{value:'video',text:'视频'},{value:'insertImage',text:'图片'}, |
| | | {value:'removeFormat',text:'格式化样式'},{value:'code',text:'源码'},{value:'line',text:'菜单分割线'} |
| | | ], |
| | | formDesignerHtml : '<div class="layui-layout layui-layout-admin">\n' + |
| | | ' <div class="layui-header">\n' + |
| | | ' <div class="layui-logo">表单设计器</div>\n' + |
| | | ' <!-- 头部区域(可配合layui已有的水平导航) -->\n' + |
| | | ' <ul class="layui-nav layui-layout-left">\n' + |
| | | ' <li class="layui-nav-item"><a href=""></a></li>\n' + |
| | | ' </ul>\n' + |
| | | ' <ul class="layui-nav layui-layout-right">\n' + |
| | | ' <li class="layui-nav-item">\n' + |
| | | ' <a id="saveJson" href="#" class="saveJson">保存</a>\n' + |
| | | ' </li>\n' + |
| | | ' <li class="layui-nav-item">\n' + |
| | | ' <a id="btnImportJson" href="#" class="importJson">导入数据</a>\n' + |
| | | ' </li>\n' + |
| | | ' <li class="layui-nav-item">\n' + |
| | | ' <a id="btnExportJson" href="#" class="exportJson">导出数据</a>\n' + |
| | | ' </li>\n' + |
| | | ' <li class="layui-nav-item">\n' + |
| | | ' <a href="#" class="previewForm">预览</a>\n' + |
| | | ' </li>\n' + |
| | | ' <li class="layui-nav-item">\n' + |
| | | ' <a href="#" class="generateCode">生成代码</a>\n' + |
| | | ' </li>\n' + |
| | | ' </ul>\n' + |
| | | ' </div>\n' + |
| | | ' <div class="layui-side">\n' + |
| | | ' <div class="layui-side-scroll" style="width: 260px;">\n' + |
| | | ' <!-- 左侧导航区域(可配合layui已有的垂直导航) -->\n' + |
| | | ' <div class="layui-tab layui-tab-brief" lay-filter="components-list">\n' + |
| | | ' <ul class="layui-tab-title">\n' + |
| | | ' <li class="layui-this">组件</li>\n' + |
| | | ' <li class="">模板</li>\n' + |
| | | ' </ul>\n' + |
| | | ' <div class="layui-tab-content">\n' + |
| | | ' <div class="layui-tab-item layui-show">\n' + |
| | | ' <div class="components-list" id="components-form-list">\n' + |
| | | ' </div>\n' + |
| | | ' </div>\n' + |
| | | ' <div class="layui-tab-item" >\n' + |
| | | ' <div id="template-form-list" class="components-list">\n' + |
| | | ' </div>\n' + |
| | | ' </div>\n' + |
| | | ' </div>\n' + |
| | | ' </div>\n' + |
| | | ' </div>\n' + |
| | | ' </div>\n' + |
| | | ' <div class="layui-body">\n' + |
| | | ' <!-- 内容主体区域 -->\n' + |
| | | ' <form class="layui-form layui-form-pane" style="height:98%;">\n' + |
| | | ' <div class="layui-form" id="formDesignerForm" lay-filter="formDesignerForm">\n' + |
| | | ' <div class="layui-row layui-empty">\n' + |
| | | ' 从左侧拖拽控件到此设计区域来添加字段\n' + |
| | | ' </div>\n' + |
| | | ' </div>\n' + |
| | | ' <button type="button" class="layui-btn" style="display: none" lay-submit lay-filter="*">立即提交</button>\n' + |
| | | ' </form>\n' + |
| | | ' </div>\n' + |
| | | ' <div class="layui-side-right">\n' + |
| | | ' <div class="layui-side-scroll" style="width: 350px;">\n' + |
| | | ' <!-- 属性导航 -->\n' + |
| | | ' <form class="layui-form layui-form-pane">\n' + |
| | | ' <div class="layui-tab layui-tab-brief" lay-filter="form-attr">\n' + |
| | | ' <ul class="layui-tab-title">\n' + |
| | | ' <li class="layui-this">字段设置</li>\n' + |
| | | ' <li>表单设置</li>\n' + |
| | | ' </ul>\n' + |
| | | ' <div class="layui-tab-content">\n' + |
| | | ' <div class="layui-tab-item layui-show" id="columnProperty">\n' + |
| | | ' </div>\n' + |
| | | ' <div class="layui-tab-item" id="formProperty">\n' + |
| | | ' <!--表单ID-->\n' + |
| | | ' <div class="layui-form-item">\n' + |
| | | ' <label class="layui-form-label">表单ID</label>\n' + |
| | | ' <div class="layui-input-block">\n' + |
| | | ' <input type="text" name="formId" required="" lay-verify="required"\n' + |
| | | ' placeholder="请输入表单ID" autocomplete="off" class="layui-input">\n' + |
| | | ' </div>\n' + |
| | | ' </div>\n' + |
| | | ' <!--//表单ID-->\n' + |
| | | ' <!--表单名称-->\n' + |
| | | ' <div class="layui-form-item">\n' + |
| | | ' <label class="layui-form-label">表单名称</label>\n' + |
| | | ' <div class="layui-input-block">\n' + |
| | | ' <input type="text" name="formName" required="" lay-verify="required"\n' + |
| | | ' placeholder="请输入表单名称" autocomplete="off" class="layui-input">\n' + |
| | | ' </div>\n' + |
| | | ' </div>\n' + |
| | | ' <!--//end-->\n' + |
| | | ' </div>\n' + |
| | | ' </div>\n' + |
| | | ' </div>\n' + |
| | | ' </form>\n' + |
| | | ' </div>\n' + |
| | | ' </div>\n' + |
| | | '</div>', |
| | | formDefaultButton:'<div class="layui-form-item">\n' + |
| | | ' <div class="layui-input-block">\n' + |
| | | ' <button type="submit" class="layui-btn" lay-submit="" lay-filter="demo1">提交</button>\n' + |
| | | ' <button type="reset" class="layui-btn layui-btn-primary">重置</button>\n' + |
| | | ' </div>\n' + |
| | | '</div>', |
| | | importHtml:'<div class="importjsoncodeview layui-layer-wrap" style="display: none;">\n' + |
| | | ' <textarea class="site-demo-text" id="import-json-code-view"></textarea>\n' + |
| | | ' <a href="javascript:;" class="layui-btn layui-btn-normal" style="margin-right:20px;" id="import-json-code">导入数据</a>\n' + |
| | | '</div>', |
| | | exportHtml:'<div class="htmlcodeview layui-layer-wrap" style="display: none;">\n' + |
| | | ' <textarea class="site-demo-text" id="generate-code-view"></textarea>\n' + |
| | | ' <a href="javascript:;" class="layui-btn layui-btn-normal" style="margin-right:20px;" id="copy-html-code">复制代码</a>\n' + |
| | | '</div>', |
| | | htmlCode: '<html>\n' + |
| | | '<head>\n' + |
| | | ' <meta charset="utf-8">\n' + |
| | | ' <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">\n' + |
| | | ' <title>表单设计器代码</title>\n' + |
| | | ' <link rel="stylesheet" href="https://www.layuicdn.com/layui-v2.5.6/css/layui.css"/>\n' + |
| | | ' <link rel="stylesheet" href="./ayq/modules/cron.css" />\n' + |
| | | ' <link rel="stylesheet" href="./ayq/modules/labelGeneration.css" />\n' + |
| | | ' <link rel="stylesheet" href="./ayq/modules/formDesigner.css" />\n' + |
| | | '</head>\n' + |
| | | '<body>\n' + |
| | | '<div id="testdemo" style="margin: 10px 20px;">\n' + |
| | | ' <form class="layui-form" style="height:100%;" id="formPreviewForm">\n' + |
| | | ' {0}\n' + |
| | | ' <div class="layui-form-item">\n' + |
| | | ' <div class="layui-input-block">\n' + |
| | | ' <button type="submit" class="layui-btn" lay-submit="" lay-filter="formPreviewForm">提交</button>\n' + |
| | | ' <button type="reset" class="layui-btn layui-btn-primary">重置</button>\n' + |
| | | ' </div>\n' + |
| | | ' </div>\n' + |
| | | ' </form>\n' + |
| | | '</div>\n' + |
| | | '<script type="text/javascript" src="https://www.layuicdn.com/layui-v2.5.6/layui.js"></script>\n' + |
| | | '<script type="text/javascript" src="./ayq/modules/Sortable/Sortable.js"></script>\n' + |
| | | '<script type="text/javascript" src="./ayq/modules/numberInput/numberInput.js"></script>\n' + |
| | | '<script type="text/javascript" src="./ayq/modules/icon/iconPicker.js"></script>\n' + |
| | | '<script type="text/javascript" src="./ayq/modules/cron/cron.js"></script>\n' + |
| | | '<script type="text/javascript" src="./ayq/modules/iceEditor/iceEditor.js"></script>\n' + |
| | | '<script type="text/javascript" src="./ayq/modules/labelGeneration/labelGeneration.js"></script>\n' + |
| | | '<script type="text/javascript" src="./ayq/js/config.js?v=100"></script>\n' + |
| | | '<script>\n' + |
| | | ' layui.use(["layer", "laytpl", "element", "form", "slider", "laydate", "rate", "colorpicker", "layedit", "carousel", "upload", "formField", "numberInput", "iconPicker", "cron", "labelGeneration"], function () {\n' + |
| | | ' var $ = layui.jquery\n' + |
| | | ' , layer = layui.layer\n' + |
| | | ' , laytpl = layui.laytpl\n' + |
| | | ' , setter = layui.cache\n' + |
| | | ' , element = layui.element\n' + |
| | | ' , slider = layui.slider\n' + |
| | | ' , laydate = layui.laydate\n' + |
| | | ' , rate = layui.rate\n' + |
| | | ' , colorpicker = layui.colorpicker\n' + |
| | | ' , carousel = layui.carousel\n' + |
| | | ' , form = layui.form\n' + |
| | | ' , upload = layui.upload\n' + |
| | | ' , layedit = layui.layedit\n' + |
| | | ' , formField = layui.formField\n' + |
| | | ' , hint = layui.hint\n' + |
| | | ' , numberInput = layui.numberInput\n' + |
| | | ' , iconPicker = layui.iconPicker\n' + |
| | | ' , cron = layui.cron\n' + |
| | | ' , labelGeneration = layui.labelGeneration;\n' + |
| | | ' {1}\n' + |
| | | ' });\n' + |
| | | '</script>\n' + |
| | | '</body>\n' + |
| | | '</html>' |
| | | } |
| | | exports('staticField', staticField); |
| | | |
| | | }); |
| | |
| | | <title>弹窗实例</title> |
| | | <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all"> |
| | | <link rel="stylesheet" href="../../static/css/admin.css?v=318" media="all"> |
| | | |
| | | <link rel="stylesheet" href="../../static/layui/lay/modules/formDesigner/cron.css" /> |
| | | <link rel="stylesheet" href="../../static/layui/lay/modules/formDesigner/labelGeneration.css" /> |
| | | <link rel="stylesheet" href="../../static/layui/lay/modules/formDesigner/formDesigner.css" /> |
| | | <!--[if lt IE 9]> |
| | | <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script> |
| | | <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> |
| | |
| | | <script type="text/html" id="formEditDialog"> |
| | | <div class="layui-fluid" style="height: 100%;padding: 0"> |
| | | <div class="layui-card"> |
| | | <div class="layui-card-header" style="padding: 10px 20px; font-size: 1.1rem"> |
| | | 表单设计 |
| | | </div> |
| | | <div class="layui-card-body"> |
| | | <div class="layui-card-body" style="height: 800px"> |
| | | <div style="height: 100%; width: 100%;" id="formDesigner"> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script> |
| | | <script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script> |
| | | <script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script> |
| | | <script type="text/javascript" src="../../static/layui/lay/modules/formDesigner/Sortable/Sortable.js"> </script> |
| | | <script> |
| | | layui.config({ |
| | | base: baseUrl + "/static/layui/lay/modules/" |
| | | }).use(['table','laydate', 'form', 'util', 'admin'], function(){ |
| | | }).use(['table','laydate', 'form', 'util', 'admin', 'formDesigner'], function(){ |
| | | var $ = layui.jquery; |
| | | var layer = layui.layer; |
| | | var admin = layui.admin; |
| | | var form = layui.form; |
| | | var table = layui.table; |
| | | var laydate = layui.laydate; |
| | | var formDesigner = layui.formDesigner; |
| | | |
| | | // 添加 |
| | | $('#eDialogAddBtn').click(function () { |
| | |
| | | // btnAlign: 'c', |
| | | content: $('#formEditDialog').html(), |
| | | success: function (layero, dIndex) { |
| | | |
| | | let formDesIdx = formDesigner.render({ |
| | | data: [], |
| | | elem:'#formDesigner' |
| | | }); |
| | | } |
| | | }) |
| | | } else if (obj.event === 'delete') { |