重绘一大波icon;修复框架子vm的props属性传递;重写datepicker组件;重写分页组件;
parent
c76a1b3264
commit
88dab988da
|
@ -19,7 +19,12 @@ const prefixer = postcss().use(
|
|||
)
|
||||
const jsOpt = {
|
||||
presets: ['es2015'],
|
||||
plugins: ['transform-es2015-modules-amd']
|
||||
plugins: [
|
||||
'transform-es2015-modules-amd',
|
||||
'transform-decorators-legacy',
|
||||
'transform-class-properties',
|
||||
'transform-object-rest-spread'
|
||||
]
|
||||
}
|
||||
const cssOpt = {
|
||||
includePaths: ['src/css/'],
|
||||
|
|
|
@ -18,7 +18,12 @@ const prefixer = postcss().use(
|
|||
)
|
||||
const jsOpt = {
|
||||
presets: ['es2015', 'minify'],
|
||||
plugins: ['transform-es2015-modules-amd']
|
||||
plugins: [
|
||||
'transform-es2015-modules-amd',
|
||||
'transform-decorators-legacy',
|
||||
'transform-class-properties',
|
||||
'transform-object-rest-spread'
|
||||
]
|
||||
}
|
||||
const cssOpt = {
|
||||
includePaths: ['src/css/'],
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "doui-yua",
|
||||
"name": "doui-anot",
|
||||
"version": "0.0.1",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
|
@ -463,6 +463,47 @@
|
|||
"babel-helper-is-void-0": "0.2.0"
|
||||
}
|
||||
},
|
||||
"babel-plugin-syntax-class-properties": {
|
||||
"version": "6.13.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
|
||||
"integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=",
|
||||
"dev": true
|
||||
},
|
||||
"babel-plugin-syntax-decorators": {
|
||||
"version": "6.13.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz",
|
||||
"integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=",
|
||||
"dev": true
|
||||
},
|
||||
"babel-plugin-syntax-object-rest-spread": {
|
||||
"version": "6.13.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
|
||||
"integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=",
|
||||
"dev": true
|
||||
},
|
||||
"babel-plugin-transform-class-properties": {
|
||||
"version": "6.24.1",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz",
|
||||
"integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-helper-function-name": "6.24.1",
|
||||
"babel-plugin-syntax-class-properties": "6.13.0",
|
||||
"babel-runtime": "6.26.0",
|
||||
"babel-template": "6.26.0"
|
||||
}
|
||||
},
|
||||
"babel-plugin-transform-decorators-legacy": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.4.tgz",
|
||||
"integrity": "sha1-dBtY9sW86eYCfgiC2cmU8E82aSU=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-plugin-syntax-decorators": "6.13.0",
|
||||
"babel-runtime": "6.26.0",
|
||||
"babel-template": "6.26.0"
|
||||
}
|
||||
},
|
||||
"babel-plugin-transform-es2015-arrow-functions": {
|
||||
"version": "6.22.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
|
||||
|
@ -721,6 +762,16 @@
|
|||
"integrity": "sha512-bPbUhkeN2Nc0KH0/A19GwQGj8w+CvdJzyu8t59VoEDgsNMQ9Bopzi5DrVkrSsVjbYUaZpzq/DYLrH+wD5K2Tig==",
|
||||
"dev": true
|
||||
},
|
||||
"babel-plugin-transform-object-rest-spread": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz",
|
||||
"integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-plugin-syntax-object-rest-spread": "6.13.0",
|
||||
"babel-runtime": "6.26.0"
|
||||
}
|
||||
},
|
||||
"babel-plugin-transform-property-literals": {
|
||||
"version": "6.8.5",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.8.5.tgz",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "doui-yua",
|
||||
"name": "doui-anot",
|
||||
"version": "0.0.1",
|
||||
"description": "基于Anot框架的doUI组件库。支持IE10+,及现代浏览器。",
|
||||
"main": "index.js",
|
||||
|
@ -13,13 +13,16 @@
|
|||
},
|
||||
"keywords": [
|
||||
"doui",
|
||||
"yua"
|
||||
"Anot"
|
||||
],
|
||||
"author": "yutent",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^7.2.5",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-plugin-transform-class-properties": "^6.24.1",
|
||||
"babel-plugin-transform-decorators-legacy": "^1.3.4",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"babel-preset-minify": "^0.2.0",
|
||||
"chalk": "^2.3.0",
|
||||
|
|
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -3297,11 +3297,12 @@
|
|||
if (/^:/.test(attr.name)) {
|
||||
var name = attr.name.match(rmsAttr)[1]
|
||||
var value = null
|
||||
if (!name || Anot.directives[name]) {
|
||||
if (!name || Anot.directives[name] || events[name]) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
value = parseExpr(attr.value, vmodels, {}).apply(0, vmodels)
|
||||
value = toJson(value)
|
||||
elem.removeAttribute(attr.name)
|
||||
if (!value) {
|
||||
return
|
||||
|
@ -4092,7 +4093,7 @@
|
|||
elem.addEventListener(type, callback, false)
|
||||
var old = binding.rollback
|
||||
binding.rollback = function() {
|
||||
elem.anotStter = null
|
||||
elem.anotSetter = null
|
||||
Anot.unbind(elem, type, callback)
|
||||
old && old()
|
||||
}
|
||||
|
@ -4196,7 +4197,7 @@
|
|||
elem.msFocus = false
|
||||
})
|
||||
}
|
||||
elem.anotStter = updateVModel //#765
|
||||
elem.anotSetter = updateVModel //#765
|
||||
watchValueInTimer(function() {
|
||||
if (root.contains(elem)) {
|
||||
if (!elem.msFocus) {
|
||||
|
@ -4346,8 +4347,8 @@
|
|||
function newSetter(value) {
|
||||
// jshint ignore:line
|
||||
setters[this.tagName].call(this, value)
|
||||
if (!this.msFocus && this.anotStter) {
|
||||
this.anotStter()
|
||||
if (!this.msFocus && this.anotSetter) {
|
||||
this.anotSetter()
|
||||
}
|
||||
}
|
||||
var inputProto = HTMLInputElement.prototype
|
||||
|
|
|
@ -42,16 +42,16 @@
|
|||
&:active {font-weight:bold;
|
||||
&::before {animation:ripple .3s cubic-bezier(0.23, 1, 0.32, 1);}
|
||||
}
|
||||
&::after {content:"\e652";}
|
||||
&::after {content:"\e692";}
|
||||
|
||||
&.prev-month {left:35px;
|
||||
&::after {content:"\e659"}
|
||||
&::after {content:"\e67c"}
|
||||
}
|
||||
&.next-month {left:auto; right:35px;
|
||||
&::after {content:"\e658"}
|
||||
&::after {content:"\e66e"}
|
||||
}
|
||||
&.next-year {left:auto; right:0;
|
||||
&::after {content:"\e653"}
|
||||
&::after {content:"\e694"}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,219 @@
|
|||
/**
|
||||
*
|
||||
* @authors yutent (yutent@doui.cc)
|
||||
* @date 2017-03-29 18:39:35
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
function getBindingCallback(elem, name, vmodels) {
|
||||
var callback = elem.getAttribute(name)
|
||||
if (callback) {
|
||||
for (var i = 0, vm; (vm = vmodels[i++]); ) {
|
||||
if (vm.hasOwnProperty(callback) && typeof vm[callback] === 'function') {
|
||||
return vm[callback]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Anot.ui.drag = '1.0.0'
|
||||
// 元素拖动
|
||||
Anot.directive('drag', {
|
||||
priority: 1500,
|
||||
init: function(binding) {
|
||||
binding.expr = '"' + binding.expr + '"'
|
||||
Anot(binding.element).css('cursor', 'move')
|
||||
|
||||
//取得拖动的3种状态回调
|
||||
//按下,且拖拽之前
|
||||
binding.beforedrag = getBindingCallback(
|
||||
binding.element,
|
||||
'data-beforedrag',
|
||||
binding.vmodels
|
||||
)
|
||||
//拖拽过程
|
||||
binding.dragging = getBindingCallback(
|
||||
binding.element,
|
||||
'data-dragging',
|
||||
binding.vmodels
|
||||
)
|
||||
// 拖拽结束,且释放鼠标
|
||||
binding.dragged = getBindingCallback(
|
||||
binding.element,
|
||||
'data-dragged',
|
||||
binding.vmodels
|
||||
)
|
||||
|
||||
//默认允许溢出可视区
|
||||
binding.overflow = true
|
||||
|
||||
//方向,x轴, y轴, xy轴
|
||||
binding.axis = 'xy'
|
||||
if (!!binding.element.dataset.axis) {
|
||||
binding.axis = binding.element.dataset.axis
|
||||
delete binding.element.dataset.axis
|
||||
}
|
||||
|
||||
//默认不限制拖拽区域
|
||||
binding.limit = false
|
||||
if (!!binding.element.dataset.limit) {
|
||||
binding.limit = binding.element.dataset.limit
|
||||
//这里,只要不为空,除parent外,其他值都默认为window, 故"可溢出"为false
|
||||
binding.overflow = false
|
||||
delete binding.element.dataset.limit
|
||||
}
|
||||
|
||||
delete binding.element.dataset.beforedrag
|
||||
delete binding.element.dataset.dragging
|
||||
delete binding.element.dataset.dragged
|
||||
},
|
||||
update: function(val) {
|
||||
var _this = this,
|
||||
target = val ? this.element.parentNode : this.element,
|
||||
$drag = Anot(this.element),
|
||||
$doc = Anot(document),
|
||||
$target = null,
|
||||
parentElem = null
|
||||
|
||||
// val值不为空时, 获取真正的拖动元素
|
||||
// 仅从父级上找
|
||||
while (val && target) {
|
||||
if (target.classList.contains(val) || target.id === val) {
|
||||
break
|
||||
} else {
|
||||
target = target.parentNode
|
||||
}
|
||||
}
|
||||
$target = Anot(target)
|
||||
// 限制范围为parent时,获取父级元素
|
||||
if (this.limit === 'parent') {
|
||||
parentElem = target.parentNode
|
||||
}
|
||||
|
||||
var dx, dy, mx, my, ox, oy, fox, foy, tw, th, ww, wh, bst, bsl
|
||||
$drag.bind('mousedown', function(ev) {
|
||||
var gcs = getComputedStyle(target),
|
||||
cst = gcs.transform.replace(/matrix\((.*)\)/, '$1'),
|
||||
offset = $target.offset()
|
||||
|
||||
cst = cst !== 'none' ? cst.split(', ') : [1, 0, 0, 1, 0, 0]
|
||||
cst[4] -= 0
|
||||
cst[5] -= 0
|
||||
|
||||
//记录初始的transform位移
|
||||
dx = cst[4]
|
||||
dy = cst[5]
|
||||
|
||||
//滚动条的偏移
|
||||
bst = $doc.scrollTop()
|
||||
bsl = $doc.scrollLeft()
|
||||
|
||||
// 计算元素的offset值, 需要修正
|
||||
ox = offset.left - dx - bsl
|
||||
oy = offset.top - dy - bst
|
||||
|
||||
mx = ev.pageX //按下鼠标的的坐标值
|
||||
my = ev.pageY //按下鼠标的的坐标值
|
||||
|
||||
// 在按下时才获取窗口大小, 是为了防止人为的改变窗口大小,导致计算不准备
|
||||
// 同时减少不必要的事件监听(页面上可能会很多可拖动元素)
|
||||
ww = window.innerWidth
|
||||
wh = window.innerHeight
|
||||
|
||||
// 同样,在点击之后获取元素的宽高,可保证获取到的是真实的值
|
||||
tw = target.clientWidth
|
||||
th = target.clientHeight
|
||||
|
||||
//拖拽前回调
|
||||
if (_this.beforedrag) {
|
||||
var result = _this.beforedrag.call(_this.vmodels, target, ox, oy)
|
||||
if (result === false) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
//限制区域, 4个值依次是: 上, 下, 左, 右
|
||||
var limit = [0, wh - th, 0, ww - tw]
|
||||
|
||||
if (_this.limit === 'parent') {
|
||||
var pgcs = getComputedStyle(parentElem),
|
||||
pcst = pgcs.transform.replace(/matrix\((.*)\)/, '$1'),
|
||||
poffset = Anot(parentElem).offset()
|
||||
|
||||
pcst = pcst !== 'none' ? pcst.split(', ') : [1, 0, 0, 1, 0, 0]
|
||||
|
||||
var pox = poffset.left - pcst[4] - bsl,
|
||||
poy = poffset.top - pcst[5] - bst
|
||||
|
||||
limit = [
|
||||
poy,
|
||||
poy + parentElem.clientHeight - th,
|
||||
pox,
|
||||
pox + parentElem.clientWidth - tw
|
||||
]
|
||||
}
|
||||
|
||||
var mvfn = $doc.bind('mousemove', function(ev) {
|
||||
//坐标轴限制
|
||||
if (_this.axis !== 'y') {
|
||||
cst[4] = ev.pageX - mx + dx
|
||||
}
|
||||
if (_this.axis !== 'x') {
|
||||
cst[5] = ev.pageY - my + dy
|
||||
}
|
||||
|
||||
;(fox = ox + cst[4]), //修正的offset
|
||||
(foy = oy + cst[5]) //修正的offset
|
||||
|
||||
//如果不允许溢出可视区
|
||||
if (!_this.overflow) {
|
||||
if (_this.axis !== 'y') {
|
||||
if (fox <= limit[2]) {
|
||||
fox = limit[2]
|
||||
//修正矩阵
|
||||
cst[4] = fox - ox
|
||||
}
|
||||
if (fox >= limit[3]) {
|
||||
fox = limit[3]
|
||||
//修正矩阵
|
||||
cst[4] = fox - ox
|
||||
}
|
||||
}
|
||||
|
||||
if (_this.axis !== 'x') {
|
||||
if (foy <= limit[0]) {
|
||||
foy = limit[0]
|
||||
//修正矩阵
|
||||
cst[5] = foy - oy
|
||||
}
|
||||
if (foy >= limit[1]) {
|
||||
foy = limit[1]
|
||||
//修正矩阵
|
||||
cst[5] = foy - oy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$target.css({
|
||||
transform: 'matrix(' + cst.join(', ') + ')'
|
||||
})
|
||||
|
||||
//拖拽过程的回调
|
||||
if (_this.dragging) {
|
||||
_this.dragging.call(_this.vmodels, target, fox, foy)
|
||||
}
|
||||
// 防止拖动到边缘时导致页面滚动
|
||||
ev.preventDefault()
|
||||
}),
|
||||
upfn = $doc.bind('mouseup', function(ev) {
|
||||
$doc.unbind('mousemove', mvfn)
|
||||
$doc.unbind('mouseup', upfn)
|
||||
//结束回调
|
||||
if (_this.dragged) {
|
||||
_this.dragged.call(_this.vmodels, target, fox, foy)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
|
@ -1,216 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* @authors yutent (yutent@doui.cc)
|
||||
* @date 2017-03-29 18:39:35
|
||||
*
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
define(['yua'], function(){
|
||||
|
||||
function getBindingCallback(elem, name, vmodels) {
|
||||
var callback = elem.getAttribute(name)
|
||||
if (callback) {
|
||||
for (var i = 0, vm; vm = vmodels[i++]; ) {
|
||||
if (vm.hasOwnProperty(callback) && typeof vm[callback] === "function") {
|
||||
return vm[callback]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
yua.ui.drag = '1.0.0'
|
||||
// 元素拖动
|
||||
yua.directive('drag', {
|
||||
priority: 1500,
|
||||
init: function(binding){
|
||||
binding.expr = '"' + binding.expr + '"'
|
||||
yua(binding.element).css('cursor', 'move')
|
||||
|
||||
//取得拖动的3种状态回调
|
||||
//按下,且拖拽之前
|
||||
binding.beforedrag = getBindingCallback(binding.element, 'data-beforedrag', binding.vmodels)
|
||||
//拖拽过程
|
||||
binding.dragging = getBindingCallback(binding.element, 'data-dragging', binding.vmodels)
|
||||
// 拖拽结束,且释放鼠标
|
||||
binding.dragged = getBindingCallback(binding.element, 'data-dragged', binding.vmodels)
|
||||
|
||||
//默认允许溢出可视区
|
||||
binding.overflow = true
|
||||
|
||||
//方向,x轴, y轴, xy轴
|
||||
binding.axis = 'xy'
|
||||
if(!!binding.element.dataset.axis){
|
||||
binding.axis = binding.element.dataset.axis
|
||||
delete binding.element.dataset.axis
|
||||
}
|
||||
|
||||
//默认不限制拖拽区域
|
||||
binding.limit = false
|
||||
if(!!binding.element.dataset.limit) {
|
||||
binding.limit = binding.element.dataset.limit
|
||||
//这里,只要不为空,除parent外,其他值都默认为window, 故"可溢出"为false
|
||||
binding.overflow = false
|
||||
delete binding.element.dataset.limit
|
||||
}
|
||||
|
||||
delete binding.element.dataset.beforedrag
|
||||
delete binding.element.dataset.dragging
|
||||
delete binding.element.dataset.dragged
|
||||
},
|
||||
update: function(val){
|
||||
var _this = this,
|
||||
target = val ? this.element.parentNode : this.element,
|
||||
$drag = yua(this.element),
|
||||
$doc = yua(document),
|
||||
$target = null,
|
||||
parentElem = null;
|
||||
|
||||
// val值不为空时, 获取真正的拖动元素
|
||||
// 仅从父级上找
|
||||
while(val && target){
|
||||
if(target.classList.contains(val) || target.id === val){
|
||||
break
|
||||
}else{
|
||||
target = target.parentNode
|
||||
}
|
||||
}
|
||||
$target = yua(target);
|
||||
// 限制范围为parent时,获取父级元素
|
||||
if(this.limit === 'parent'){
|
||||
parentElem = target.parentNode
|
||||
}
|
||||
|
||||
|
||||
var dx,dy,mx,my,ox,oy,fox,foy,tw,th,ww,wh,bst,bsl;
|
||||
$drag.bind('mousedown', function(ev){
|
||||
var gcs = getComputedStyle(target),
|
||||
cst = gcs.transform.replace(/matrix\((.*)\)/, '$1'),
|
||||
offset = $target.offset();
|
||||
|
||||
cst = cst !== 'none' ? cst.split(', ') : [1,0,0,1,0,0]
|
||||
cst[4] -= 0
|
||||
cst[5] -= 0
|
||||
|
||||
//记录初始的transform位移
|
||||
dx = cst[4]
|
||||
dy = cst[5]
|
||||
|
||||
//滚动条的偏移
|
||||
bst = $doc.scrollTop()
|
||||
bsl = $doc.scrollLeft()
|
||||
|
||||
// 计算元素的offset值, 需要修正
|
||||
ox = offset.left - dx - bsl
|
||||
oy = offset.top - dy - bst
|
||||
|
||||
mx = ev.pageX //按下鼠标的的坐标值
|
||||
my = ev.pageY //按下鼠标的的坐标值
|
||||
|
||||
// 在按下时才获取窗口大小, 是为了防止人为的改变窗口大小,导致计算不准备
|
||||
// 同时减少不必要的事件监听(页面上可能会很多可拖动元素)
|
||||
ww = window.innerWidth;
|
||||
wh = window.innerHeight;
|
||||
|
||||
// 同样,在点击之后获取元素的宽高,可保证获取到的是真实的值
|
||||
tw = target.clientWidth;
|
||||
th = target.clientHeight;
|
||||
|
||||
//拖拽前回调
|
||||
if(_this.beforedrag){
|
||||
var result = _this.beforedrag.call(_this.vmodels, target, ox, oy)
|
||||
if(result === false){
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
//限制区域, 4个值依次是: 上, 下, 左, 右
|
||||
var limit = [0, wh - th, 0, ww - tw]
|
||||
|
||||
if(_this.limit === 'parent') {
|
||||
var pgcs = getComputedStyle(parentElem),
|
||||
pcst = pgcs.transform.replace(/matrix\((.*)\)/, '$1'),
|
||||
poffset = yua(parentElem).offset();
|
||||
|
||||
pcst = pcst !== 'none' ? pcst.split(', ') : [1,0,0,1,0,0]
|
||||
|
||||
var pox = poffset.left - pcst[4] - bsl,
|
||||
poy = poffset.top - pcst[5] - bst;
|
||||
|
||||
limit = [poy, poy + parentElem.clientHeight - th, pox, pox + parentElem.clientWidth - tw]
|
||||
}
|
||||
|
||||
var mvfn = $doc.bind('mousemove', function(ev){
|
||||
|
||||
//坐标轴限制
|
||||
if(_this.axis !== 'y'){
|
||||
cst[4] = ev.pageX - mx + dx
|
||||
}
|
||||
if(_this.axis !== 'x'){
|
||||
cst[5] = ev.pageY - my + dy
|
||||
}
|
||||
|
||||
|
||||
fox = ox + cst[4], //修正的offset
|
||||
foy = oy + cst[5]; //修正的offset
|
||||
|
||||
|
||||
//如果不允许溢出可视区
|
||||
if(!_this.overflow){
|
||||
if(_this.axis !== 'y'){
|
||||
if(fox <= limit[2]) {
|
||||
fox = limit[2]
|
||||
//修正矩阵
|
||||
cst[4] = fox - ox
|
||||
}
|
||||
if(fox >= limit[3]){
|
||||
fox = limit[3]
|
||||
//修正矩阵
|
||||
cst[4] = fox - ox
|
||||
}
|
||||
}
|
||||
|
||||
if(_this.axis !== 'x'){
|
||||
if(foy <= limit[0]) {
|
||||
foy = limit[0]
|
||||
//修正矩阵
|
||||
cst[5] = foy - oy
|
||||
}
|
||||
if(foy >= limit[1]){
|
||||
foy = limit[1]
|
||||
//修正矩阵
|
||||
cst[5] = foy - oy
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$target.css({
|
||||
transform: 'matrix(' + cst.join(', ') + ')'
|
||||
})
|
||||
|
||||
//拖拽过程的回调
|
||||
if(_this.dragging){
|
||||
_this.dragging.call(_this.vmodels, target, fox, foy)
|
||||
}
|
||||
// 防止拖动到边缘时导致页面滚动
|
||||
ev.preventDefault()
|
||||
}),
|
||||
upfn = $doc.bind('mouseup', function(ev){
|
||||
$doc.unbind('mousemove', mvfn)
|
||||
$doc.unbind('mouseup', upfn)
|
||||
//结束回调
|
||||
if(_this.dragged){
|
||||
_this.dragged.call(_this.vmodels, target, fox, foy)
|
||||
}
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
})
|
File diff suppressed because it is too large
Load Diff
|
@ -1,578 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* @authors yutent (yutent@doui.cc)
|
||||
* @date 2016-09-21 01:36:29
|
||||
*
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
define(['yua', 'lib/drag', 'css!./skin/def'], function(yua){
|
||||
|
||||
|
||||
var layerDom = {},
|
||||
layerObj = {},
|
||||
unique = null, //储存当前打开的1/2/3类型的弹窗
|
||||
lid = 0,
|
||||
defconf = {
|
||||
type: 1, // 弹窗类型
|
||||
skin: 'def', //默认主题
|
||||
icon: 1, //图标类型
|
||||
background: '#fff',
|
||||
shade: true, //遮罩
|
||||
shadeClose: false, //遮罩点击关闭弹窗
|
||||
radius: '0px', //弹窗圆角半径
|
||||
area: ['auto', 'auto'],
|
||||
title: '', //弹窗主标题(在工具栏上的)
|
||||
menubar: true, //是否显示菜单栏
|
||||
content: '', // 弹窗的内容
|
||||
fixed: false, //是否固定不可拖拽
|
||||
offset: null, //弹窗出来时的坐标, 为数组,可有4个值,依次是 上右下左
|
||||
btns: ['确定', '取消'], //弹窗的2个按钮的文字
|
||||
yes: close, //确定按钮对应的回调
|
||||
no: close, //取消按钮对应的回调
|
||||
success: null //弹窗初始化完成时的回调
|
||||
};
|
||||
|
||||
function uuid(){
|
||||
return 'layer-' + (++lid)
|
||||
}
|
||||
|
||||
|
||||
function close(id){
|
||||
if(typeof id !== 'string' && typeof id !== 'number'){
|
||||
return console.error(new Error('要关闭的layer实例不存在'))
|
||||
}
|
||||
if(/^\$wrap\-/.test(id) || layerObj['$wrap-' + id]){
|
||||
|
||||
try {
|
||||
id = (layerObj['$wrap-' + id] ? '$wrap-' : '') + id;
|
||||
//未显示过,忽略
|
||||
if(!layerObj[id].show){
|
||||
return
|
||||
}
|
||||
layerObj[id].parentElem.replaceChild(layerObj[id].wrap, layerDom[id][1])
|
||||
unique = null
|
||||
}catch(err){}
|
||||
}else{
|
||||
try {
|
||||
document.body.removeChild(layerDom[id][1])
|
||||
document.body.removeChild(layerDom[id][0])
|
||||
unique = null
|
||||
}catch(err){}
|
||||
|
||||
delete layerDom[id]
|
||||
delete yua.vmodels[id]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function reapeat(str, num){
|
||||
var idx = 0,
|
||||
result = ''
|
||||
while(idx < num){
|
||||
result += str
|
||||
idx++
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function fixOffset(val){
|
||||
if(!val && val !== 0){
|
||||
return 'auto'
|
||||
}else{
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
var __constructor = function(conf){
|
||||
if(conf){
|
||||
this.ready(conf).append().show()
|
||||
}
|
||||
},
|
||||
__layer = {
|
||||
alert: function(msg, conf){
|
||||
if(typeof conf === 'function'){
|
||||
conf = {yes: conf}
|
||||
}else if(typeof conf === 'object'){
|
||||
conf = conf
|
||||
}else{
|
||||
conf = {}
|
||||
}
|
||||
conf.icon = 6
|
||||
conf.content = msg
|
||||
return __layer.open(conf)
|
||||
},
|
||||
confirm: function(msg, conf){
|
||||
if(typeof conf === 'function'){
|
||||
conf = {yes: conf}
|
||||
}else if(typeof conf === 'object'){
|
||||
conf = conf
|
||||
}else{
|
||||
conf = {}
|
||||
}
|
||||
conf.type = 2
|
||||
conf.icon = 8
|
||||
conf.content = msg
|
||||
return __layer.open(conf)
|
||||
},
|
||||
msg: function(msg, conf){
|
||||
if(typeof conf !== 'object'){
|
||||
var tmp = conf
|
||||
conf = {timeout: 2500}
|
||||
if(typeof tmp === 'number'){
|
||||
conf.icon = tmp
|
||||
}
|
||||
}
|
||||
|
||||
if(!conf.hasOwnProperty('timeout')){
|
||||
conf.timeout = 2500
|
||||
}
|
||||
|
||||
conf.specialMode = true;//特殊模式
|
||||
conf.content = '<p class="msg-box">' + msg + '</p>'
|
||||
conf.type = 7
|
||||
conf.fixed = true
|
||||
conf.shade = false
|
||||
conf.menubar = false
|
||||
conf.radius = '5px'
|
||||
return __layer.open(conf)
|
||||
},
|
||||
loading: function(style, time, cb){
|
||||
style = style >>> 0
|
||||
|
||||
if(typeof time === 'function'){
|
||||
cb = time;
|
||||
time = 0
|
||||
} else{
|
||||
time = time >>> 0
|
||||
if(typeof cb !== 'function'){
|
||||
cb = yua.noop
|
||||
}
|
||||
}
|
||||
return __layer.open({type: 6, load: style, yes: cb, timeout: time, menubar: false, background: 'none', fixed: true})
|
||||
},
|
||||
tips: function(msg, elem, conf){
|
||||
if(!(elem instanceof HTMLElement)){
|
||||
return console.error(new Error('tips类型必须指定一个目标容器'))
|
||||
}
|
||||
if(typeof conf !== 'object'){
|
||||
var tmp = conf
|
||||
conf = {timeout: 2500}
|
||||
if(typeof tmp === 'number'){
|
||||
conf.icon = tmp
|
||||
}
|
||||
}
|
||||
if(!conf.hasOwnProperty('timeout')){
|
||||
conf.timeout = 2500
|
||||
}
|
||||
if(!conf.background){
|
||||
conf.background = 'rgba(0,0,0,.5)'
|
||||
}
|
||||
if(!conf.color){
|
||||
conf.color = '#fff'
|
||||
}
|
||||
conf.$elem = elem
|
||||
conf.content = msg
|
||||
conf.type = 5;
|
||||
conf.icon = 0;
|
||||
conf.fixed = true;
|
||||
conf.shade = false;
|
||||
conf.menubar = false;
|
||||
return __layer.open(conf)
|
||||
},
|
||||
prompt: function(msg, callback){
|
||||
if(typeof callback !== 'function'){
|
||||
return console.error('argument [callback] requires a function, but ' + (typeof callback) + ' given')
|
||||
}
|
||||
var conf = {
|
||||
type: 3,
|
||||
icon: 7,
|
||||
prompt: '',
|
||||
title: msg,
|
||||
content: '<input class="prompt-value" :duplex="prompt" />',
|
||||
yes: function(id){
|
||||
callback(id, yua.vmodels[id].prompt)
|
||||
}
|
||||
}
|
||||
return __layer.open(conf)
|
||||
},
|
||||
use: function(skin, callback){
|
||||
require(['css!./skin/' + skin], callback)
|
||||
},
|
||||
close: close,
|
||||
open: function(conf){
|
||||
if(typeof conf === 'string'){
|
||||
conf = '$wrap-' + conf
|
||||
if(!layerObj[conf]){
|
||||
throw new Error('layer实例不存在')
|
||||
}else{
|
||||
//只能显示一个实例
|
||||
if(layerObj[conf].show){
|
||||
return
|
||||
}
|
||||
layerObj[conf].show = true
|
||||
|
||||
if(!yua.vmodels[conf]){
|
||||
yua.define(layerObj[conf].obj.init)
|
||||
}
|
||||
|
||||
yua.scan(layerDom[conf][1])
|
||||
layerObj[conf].obj.show()
|
||||
|
||||
layerObj[conf].parentElem.appendChild(layerDom[conf][1])
|
||||
layerObj[conf].parentElem.replaceChild(layerDom[conf][1], layerObj[conf].wrap)
|
||||
}
|
||||
}else{
|
||||
return new __constructor(conf).init.$id
|
||||
}
|
||||
},
|
||||
version: '0.0.1-base'
|
||||
};
|
||||
|
||||
/*type: { // 弹窗类型对应的id值
|
||||
1: 'alert',
|
||||
2: 'confirm',
|
||||
3: 'prompt',
|
||||
4: 'iframe',
|
||||
5: 'tips',
|
||||
6: 'loading',
|
||||
7: 'msg',
|
||||
}*/
|
||||
__constructor.prototype = {
|
||||
dot: { //loading的子元素数量
|
||||
0: 4,
|
||||
1: 9,
|
||||
2: 2,
|
||||
3: 3,
|
||||
4: 2,
|
||||
5: 5,
|
||||
6: 5,
|
||||
7: 5
|
||||
},
|
||||
timeout: null,
|
||||
create: function(){
|
||||
var layBox = document.createElement('div'),
|
||||
coverBox = document.createElement('div');
|
||||
|
||||
coverBox.className = 'do-layer-cover type-' + this.init.type
|
||||
// 允许点击遮罩关闭弹层时, 添加控制器
|
||||
if(this.init.shadeClose){
|
||||
coverBox.setAttribute(':controller', this.cInit.$id)
|
||||
coverBox.setAttribute(':click', 'close(\'' + this.init.$id + '\')')
|
||||
}
|
||||
|
||||
layBox.className = 'do-layer skin-'
|
||||
+ this.init.skin
|
||||
+ (this.init.type === 5 && ' active' || '')
|
||||
+ ' type-'
|
||||
+ ((!this.init.specialMode && this.init.type === 7) ? 'unspecial' : this.init.type);
|
||||
|
||||
//暂时隐藏,避免修正定位时,能看到闪一下
|
||||
layBox.style.visibility = 'hidden'
|
||||
layBox.style.borderRadius = this.init.radius
|
||||
|
||||
layBox.setAttribute(':controller', this.init.$id)
|
||||
|
||||
//没有菜单栏, 且未禁止拖拽,则加上可拖拽属性
|
||||
if(!this.init.menubar && !this.init.fixed){
|
||||
layBox.setAttribute(':drag', '')
|
||||
layBox.setAttribute('data-limit', 'window')
|
||||
}
|
||||
|
||||
//弹窗的宽高
|
||||
var boxcss = ''
|
||||
if(this.init.area[0] !== 'auto'){
|
||||
boxcss += 'width: ' + this.init.area[0] + ';'
|
||||
}
|
||||
if(this.init.area[1] !== 'auto'){
|
||||
boxcss += 'height: ' + this.init.area[1] + ';'
|
||||
}
|
||||
|
||||
layBox.innerHTML = this.getMenubar()
|
||||
+ '<div class="layer-content do-fn-cl '
|
||||
+ (this.init.icon === 0 && 'none-icon' || '')
|
||||
+ '" style="'
|
||||
+ boxcss
|
||||
+ '">'
|
||||
+ this.getCont()
|
||||
+ '</div>'
|
||||
+ this.getBtns()
|
||||
+ (this.init.type === 5 && '<i class="arrow" style="border-top-color: '
|
||||
+ this.init.background
|
||||
+ '"></i>' || '')
|
||||
|
||||
return [this.init.shade ? coverBox : null, layBox]
|
||||
},
|
||||
getCont: function(){
|
||||
if(this.init.type === 6){
|
||||
return this.getLoading(this.init.load)
|
||||
}else{
|
||||
return this.getIcon()
|
||||
+ '<div class="detail" :html="content"></div>'
|
||||
}
|
||||
},
|
||||
getLoading: function(style){
|
||||
return '<div class="do-ui-load load-style-'
|
||||
+ style
|
||||
+ '">'
|
||||
+ '<span class="dot-box">'
|
||||
+ reapeat('<i></i>', this.dot[style])
|
||||
+ '</span>'
|
||||
+ '</div>'
|
||||
},
|
||||
//获取窗口导航条
|
||||
getMenubar: function(){
|
||||
var html = ''
|
||||
if(this.init.menubar){
|
||||
html += '<div class="layer-title do-fn-noselect" ';
|
||||
//可拖拽
|
||||
if(!this.init.fixed){
|
||||
html += ':drag="do-layer" data-limit="window" '
|
||||
}
|
||||
|
||||
html += '>{{title}}'
|
||||
+ '<a class="action-close deficon" :click="no(\'' + this.init.$id + '\')"></a>'
|
||||
+ '</div>'
|
||||
}
|
||||
return html
|
||||
},
|
||||
//获取窗口内容的图标
|
||||
getIcon: function(){
|
||||
if(this.init.icon === 0){
|
||||
return ''
|
||||
}
|
||||
if(this.init.type < 4 || this.init.type === 5 || this.init.specialMode){
|
||||
return '<span class="deficon icon-' + this.init.icon + '"></span>'
|
||||
}
|
||||
return ''
|
||||
},
|
||||
// 获取窗口按钮
|
||||
getBtns: function(){
|
||||
if(this.init.type > 3){
|
||||
return ''
|
||||
}else{
|
||||
var html = '<div class="layer-btns do-fn-noselect">';
|
||||
if(this.init.type > 1){
|
||||
html += '<a href="javascript:;" class="action-no" '
|
||||
+ ':click="no(\'' + this.init.$id + '\')" '
|
||||
+ ':text="btns[1]"></a>'
|
||||
+ '<a href="javascript:;" class="action-yes" '
|
||||
+ ':click="yes(\'' + this.init.$id + '\')" '
|
||||
+ ':text="btns[0]"></a>'
|
||||
}else{
|
||||
html += '<a href="javascript:;" class="action-yes" '
|
||||
+ ':click="yes(\'' + this.init.$id + '\')" '
|
||||
+ ':text="btns[0]"></a>'
|
||||
}
|
||||
html += '</div>'
|
||||
|
||||
return html
|
||||
}
|
||||
},
|
||||
append: function(){
|
||||
//如果有已经打开的弹窗,则关闭
|
||||
if(unique){
|
||||
__layer.close(unique)
|
||||
}
|
||||
if(this.init.type < 4){
|
||||
unique = this.init.$id
|
||||
}
|
||||
layerDom[this.init.$id] = this.create()
|
||||
if(layerDom[this.init.$id][0]){
|
||||
document.body.appendChild(layerDom[this.init.$id][0])
|
||||
//仅在允许点击遮罩时,初始化控制器,减少资源消耗
|
||||
if(this.init.shadeClose){
|
||||
yua.define(this.cInit)
|
||||
yua.scan(layerDom[this.init.$id][0])
|
||||
}
|
||||
}
|
||||
|
||||
document.body.appendChild(layerDom[this.init.$id][1])
|
||||
yua.define(this.init)
|
||||
yua.scan(layerDom[this.init.$id][1])
|
||||
return this
|
||||
},
|
||||
show: function(){
|
||||
var _this = this;
|
||||
|
||||
setTimeout(function(){
|
||||
var style = {visibility: '', background: _this.init.background},
|
||||
css = getComputedStyle(layerDom[_this.init.$id][1]);
|
||||
|
||||
if(_this.init.type === 5){
|
||||
style.color = _this.init.color
|
||||
|
||||
var $elem = yua(_this.init.$elem),
|
||||
ew = $elem.innerWidth(),
|
||||
ol = $elem.offset().left - document.body.scrollLeft,
|
||||
ot = $elem.offset().top - document.body.scrollTop;
|
||||
|
||||
style.left = ol + (ew * 0.7)
|
||||
style.top = ot - parseInt(css.height) - 8
|
||||
|
||||
}else{
|
||||
if(_this.init.offset){
|
||||
style.top = fixOffset(_this.init.offset[0])
|
||||
style.right = fixOffset(_this.init.offset[1])
|
||||
style.bottom = fixOffset(_this.init.offset[2])
|
||||
style.left = fixOffset(_this.init.offset[3])
|
||||
}else{
|
||||
style = yua.mix(style, {
|
||||
marginLeft: -parseInt(css.width) / 2,
|
||||
marginTop: -parseInt(css.height) / 2,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
yua(layerDom[_this.init.$id][1]).css(style)
|
||||
|
||||
}, 4)
|
||||
|
||||
|
||||
if(this.init.success && typeof this.init.success === 'function'){
|
||||
//弹窗成功的回调
|
||||
this.init.success(this.init.$id)
|
||||
}
|
||||
// loading类型,回调需要自动触发
|
||||
if(this.init.type > 3) {
|
||||
//大于0自动触发超时关闭
|
||||
if(this.init.timeout > 0){
|
||||
clearTimeout(this.timeout)
|
||||
this.timeout = setTimeout(function(){
|
||||
|
||||
clearTimeout(_this.timeout)
|
||||
__layer.close(_this.init.$id)
|
||||
|
||||
// 为loading类型时,自动关闭同时触发回调
|
||||
if(_this.init.type === 6){
|
||||
_this.init.yes(_this.init.$id)
|
||||
}
|
||||
|
||||
}, this.init.timeout)
|
||||
|
||||
} else if(this.init.type === 6) {
|
||||
// loading类型, 非自动关闭时, 主动触发回调
|
||||
this.init.yes(this.init.$id)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
ready: function(conf){
|
||||
this.init = yua.mix({}, defconf, conf)
|
||||
if(!this.init.$id){
|
||||
this.init.$id = uuid();
|
||||
}
|
||||
if(this.init.icon > 17){
|
||||
this.icon.icon = 17
|
||||
}
|
||||
//base版没有iframe类型
|
||||
if(this.init.type === 4){
|
||||
this.icon.type = 7
|
||||
}
|
||||
this.cInit = {
|
||||
$id: this.init.$id + '-c',
|
||||
close: this.init.shadeClose ? close : yua.noop
|
||||
};
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
yua.directive('layer', {
|
||||
priority: 1400,
|
||||
init: function(binding){
|
||||
if(!binding.param){
|
||||
binding.element.style.display = 'none'
|
||||
}
|
||||
},
|
||||
update: function(val){
|
||||
if(!val){
|
||||
return console.error(new Error(':layer指令格式不正确或无效属性. [' + this.name + '="' + this.expr) + '"]')
|
||||
}
|
||||
|
||||
var _this = this,
|
||||
init = Object.assign({}, this.element.dataset);
|
||||
|
||||
if(!this.param){
|
||||
init.type = 7;
|
||||
init.$id = '$wrap-' + val;
|
||||
if(!init.hasOwnProperty('menubar')){
|
||||
init.menubar = false;
|
||||
}
|
||||
|
||||
var tmp = new __constructor().ready(init);
|
||||
|
||||
tmp.init.content = this.element.cloneNode(true);
|
||||
|
||||
layerObj[tmp.init.$id] = {obj: tmp, parentElem: this.element.parentNode, wrap: this.element, show: false};
|
||||
layerDom[tmp.init.$id] = tmp.create();
|
||||
}else if(this.param === 'tips'){
|
||||
var $elem = yua(this.element),
|
||||
ew = $elem.innerWidth(),
|
||||
ol = $elem.offset().left - document.body.scrollLeft,
|
||||
ot = $elem.offset().top - document.body.scrollTop,
|
||||
tipsBox = document.createElement('div'),
|
||||
tipsArrow = document.createElement('i'),
|
||||
tipsCont = document.createElement('div');
|
||||
|
||||
|
||||
tipsBox.className = 'do-layer skin-def type-5'
|
||||
tipsBox.style.left = ol + (ew * 0.7) + 'px'
|
||||
if(init.background){
|
||||
tipsBox.style.background = init.background
|
||||
tipsArrow.style.borderTopColor = init.background
|
||||
}
|
||||
if(init.color){
|
||||
tipsBox.style.color = init.color
|
||||
}
|
||||
tipsCont.className = 'layer-content'
|
||||
tipsCont.textContent = val
|
||||
tipsArrow.className = 'arrow'
|
||||
tipsBox.appendChild(tipsCont)
|
||||
tipsBox.appendChild(tipsArrow)
|
||||
|
||||
|
||||
|
||||
yua(document).bind('scroll', function(){
|
||||
ol = $elem.offset().left - document.body.scrollLeft;
|
||||
ot = $elem.offset().top - document.body.scrollTop;
|
||||
|
||||
tipsBox.style.left = ol + (ew * 0.7) + 'px'
|
||||
tipsBox.style.top = (ot - tipsBox.offsetHeight - 8) + 'px'
|
||||
})
|
||||
|
||||
$elem.bind('mouseenter', function(ev){
|
||||
_this.element.parentNode.appendChild(tipsBox)
|
||||
clearTimeout(_this.showTime)
|
||||
clearTimeout(_this.hideTime)
|
||||
_this.showTime = setTimeout(function(){
|
||||
tipsBox.style.top = (ot - tipsBox.offsetHeight - 8) + 'px'
|
||||
tipsBox.classList.add('active')
|
||||
|
||||
}, 4)
|
||||
|
||||
})
|
||||
$elem.bind('mouseleave', function(){
|
||||
_this.hideTime = setTimeout(function(){
|
||||
clearTimeout(_this.hideTime)
|
||||
try{
|
||||
_this.element.parentNode.removeChild(tipsBox)
|
||||
}catch(err){}
|
||||
}, 150)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
if(!window.layer)
|
||||
window.layer = __layer
|
||||
|
||||
|
||||
return __layer
|
||||
|
||||
})
|
|
@ -1,578 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* @authors yutent (yutent@doui.cc)
|
||||
* @date 2016-09-21 01:36:29
|
||||
*
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
define(['yua', 'lib/drag', 'css!./skin/def'], function(yua){
|
||||
|
||||
|
||||
var layerDom = {},
|
||||
layerObj = {},
|
||||
unique = null, //储存当前打开的1/2/3类型的弹窗
|
||||
lid = 0,
|
||||
defconf = {
|
||||
type: 1, // 弹窗类型
|
||||
skin: 'def', //默认主题
|
||||
icon: 1, //图标类型
|
||||
background: '#fff',
|
||||
shade: true, //遮罩
|
||||
shadeClose: false, //遮罩点击关闭弹窗
|
||||
radius: '0px', //弹窗圆角半径
|
||||
area: ['auto', 'auto'],
|
||||
title: '', //弹窗主标题(在工具栏上的)
|
||||
menubar: true, //是否显示菜单栏
|
||||
content: '', // 弹窗的内容
|
||||
fixed: false, //是否固定不可拖拽
|
||||
offset: null, //弹窗出来时的坐标, 为数组,可有4个值,依次是 上右下左
|
||||
btns: ['确定', '取消'], //弹窗的2个按钮的文字
|
||||
yes: close, //确定按钮对应的回调
|
||||
no: close, //取消按钮对应的回调
|
||||
success: null //弹窗初始化完成时的回调
|
||||
};
|
||||
|
||||
function uuid(){
|
||||
return 'layer-' + (++lid)
|
||||
}
|
||||
|
||||
|
||||
function close(id){
|
||||
if(typeof id !== 'string' && typeof id !== 'number'){
|
||||
return console.error(new Error('要关闭的layer实例不存在'))
|
||||
}
|
||||
if(/^\$wrap\-/.test(id) || layerObj['$wrap-' + id]){
|
||||
|
||||
try {
|
||||
id = (layerObj['$wrap-' + id] ? '$wrap-' : '') + id;
|
||||
//未显示过,忽略
|
||||
if(!layerObj[id].show){
|
||||
return
|
||||
}
|
||||
layerObj[id].parentElem.replaceChild(layerObj[id].wrap, layerDom[id][1])
|
||||
unique = null
|
||||
}catch(err){}
|
||||
}else{
|
||||
try {
|
||||
document.body.removeChild(layerDom[id][1])
|
||||
document.body.removeChild(layerDom[id][0])
|
||||
unique = null
|
||||
}catch(err){}
|
||||
|
||||
delete layerDom[id]
|
||||
delete yua.vmodels[id]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function reapeat(str, num){
|
||||
var idx = 0,
|
||||
result = ''
|
||||
while(idx < num){
|
||||
result += str
|
||||
idx++
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function fixOffset(val){
|
||||
if(!val && val !== 0){
|
||||
return 'auto'
|
||||
}else{
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
var __constructor = function(conf){
|
||||
if(conf){
|
||||
this.ready(conf).append().show()
|
||||
}
|
||||
},
|
||||
__layer = {
|
||||
alert: function(msg, conf){
|
||||
if(typeof conf === 'function'){
|
||||
conf = {yes: conf}
|
||||
}else if(typeof conf === 'object'){
|
||||
conf = conf
|
||||
}else{
|
||||
conf = {}
|
||||
}
|
||||
conf.icon = 6
|
||||
conf.content = msg
|
||||
return __layer.open(conf)
|
||||
},
|
||||
confirm: function(msg, conf){
|
||||
if(typeof conf === 'function'){
|
||||
conf = {yes: conf}
|
||||
}else if(typeof conf === 'object'){
|
||||
conf = conf
|
||||
}else{
|
||||
conf = {}
|
||||
}
|
||||
conf.type = 2
|
||||
conf.icon = 8
|
||||
conf.content = msg
|
||||
return __layer.open(conf)
|
||||
},
|
||||
msg: function(msg, conf){
|
||||
if(typeof conf !== 'object'){
|
||||
var tmp = conf
|
||||
conf = {timeout: 2500}
|
||||
if(typeof tmp === 'number'){
|
||||
conf.icon = tmp
|
||||
}
|
||||
}
|
||||
|
||||
if(!conf.hasOwnProperty('timeout')){
|
||||
conf.timeout = 2500
|
||||
}
|
||||
|
||||
conf.specialMode = true;//特殊模式
|
||||
conf.content = '<p class="msg-box">' + msg + '</p>'
|
||||
conf.type = 7
|
||||
conf.fixed = true
|
||||
conf.shade = false
|
||||
conf.menubar = false
|
||||
conf.radius = '5px'
|
||||
return __layer.open(conf)
|
||||
},
|
||||
loading: function(style, time, cb){
|
||||
style = style >>> 0
|
||||
|
||||
if(typeof time === 'function'){
|
||||
cb = time;
|
||||
time = 0
|
||||
} else{
|
||||
time = time >>> 0
|
||||
if(typeof cb !== 'function'){
|
||||
cb = yua.noop
|
||||
}
|
||||
}
|
||||
return __layer.open({type: 6, load: style, yes: cb, timeout: time, menubar: false, background: 'none', fixed: true})
|
||||
},
|
||||
tips: function(msg, elem, conf){
|
||||
if(!(elem instanceof HTMLElement)){
|
||||
return console.error(new Error('tips类型必须指定一个目标容器'))
|
||||
}
|
||||
if(typeof conf !== 'object'){
|
||||
var tmp = conf
|
||||
conf = {timeout: 2500}
|
||||
if(typeof tmp === 'number'){
|
||||
conf.icon = tmp
|
||||
}
|
||||
}
|
||||
if(!conf.hasOwnProperty('timeout')){
|
||||
conf.timeout = 2500
|
||||
}
|
||||
if(!conf.background){
|
||||
conf.background = 'rgba(0,0,0,.5)'
|
||||
}
|
||||
if(!conf.color){
|
||||
conf.color = '#fff'
|
||||
}
|
||||
conf.$elem = elem
|
||||
conf.content = msg
|
||||
conf.type = 5;
|
||||
conf.icon = 0;
|
||||
conf.fixed = true;
|
||||
conf.shade = false;
|
||||
conf.menubar = false;
|
||||
return __layer.open(conf)
|
||||
},
|
||||
prompt: function(msg, callback){
|
||||
if(typeof callback !== 'function'){
|
||||
return console.error('argument [callback] requires a function, but ' + (typeof callback) + ' given')
|
||||
}
|
||||
var conf = {
|
||||
type: 3,
|
||||
icon: 7,
|
||||
prompt: '',
|
||||
title: msg,
|
||||
content: '<input class="prompt-value" :duplex="prompt" />',
|
||||
yes: function(id){
|
||||
callback(id, yua.vmodels[id].prompt)
|
||||
}
|
||||
}
|
||||
return __layer.open(conf)
|
||||
},
|
||||
use: function(skin, callback){
|
||||
require(['css!./skin/' + skin], callback)
|
||||
},
|
||||
close: close,
|
||||
open: function(conf){
|
||||
if(typeof conf === 'string'){
|
||||
conf = '$wrap-' + conf
|
||||
if(!layerObj[conf]){
|
||||
throw new Error('layer实例不存在')
|
||||
}else{
|
||||
//只能显示一个实例
|
||||
if(layerObj[conf].show){
|
||||
return
|
||||
}
|
||||
layerObj[conf].show = true
|
||||
|
||||
if(!yua.vmodels[conf]){
|
||||
yua.define(layerObj[conf].obj.init)
|
||||
}
|
||||
|
||||
yua.scan(layerDom[conf][1])
|
||||
layerObj[conf].obj.show()
|
||||
|
||||
layerObj[conf].parentElem.appendChild(layerDom[conf][1])
|
||||
layerObj[conf].parentElem.replaceChild(layerDom[conf][1], layerObj[conf].wrap)
|
||||
}
|
||||
}else{
|
||||
return new __constructor(conf).init.$id
|
||||
}
|
||||
},
|
||||
version: '0.0.1-base'
|
||||
};
|
||||
|
||||
/*type: { // 弹窗类型对应的id值
|
||||
1: 'alert',
|
||||
2: 'confirm',
|
||||
3: 'prompt',
|
||||
4: 'iframe',
|
||||
5: 'tips',
|
||||
6: 'loading',
|
||||
7: 'msg',
|
||||
}*/
|
||||
__constructor.prototype = {
|
||||
dot: { //loading的子元素数量
|
||||
0: 4,
|
||||
1: 9,
|
||||
2: 2,
|
||||
3: 3,
|
||||
4: 2,
|
||||
5: 5,
|
||||
6: 5,
|
||||
7: 5
|
||||
},
|
||||
timeout: null,
|
||||
create: function(){
|
||||
var layBox = document.createElement('div'),
|
||||
coverBox = document.createElement('div');
|
||||
|
||||
coverBox.className = 'do-layer-cover type-' + this.init.type
|
||||
// 允许点击遮罩关闭弹层时, 添加控制器
|
||||
if(this.init.shadeClose){
|
||||
coverBox.setAttribute(':controller', this.cInit.$id)
|
||||
coverBox.setAttribute(':click', 'close(\'' + this.init.$id + '\')')
|
||||
}
|
||||
|
||||
layBox.className = 'do-layer skin-'
|
||||
+ this.init.skin
|
||||
+ (this.init.type === 5 && ' active' || '')
|
||||
+ ' type-'
|
||||
+ ((!this.init.specialMode && this.init.type === 7) ? 'unspecial' : this.init.type);
|
||||
|
||||
//暂时隐藏,避免修正定位时,能看到闪一下
|
||||
layBox.style.visibility = 'hidden'
|
||||
layBox.style.borderRadius = this.init.radius
|
||||
|
||||
layBox.setAttribute(':controller', this.init.$id)
|
||||
|
||||
//没有菜单栏, 且未禁止拖拽,则加上可拖拽属性
|
||||
if(!this.init.menubar && !this.init.fixed){
|
||||
layBox.setAttribute(':drag', '')
|
||||
layBox.setAttribute('data-limit', 'window')
|
||||
}
|
||||
|
||||
//弹窗的宽高
|
||||
var boxcss = ''
|
||||
if(this.init.area[0] !== 'auto'){
|
||||
boxcss += 'width: ' + this.init.area[0] + ';'
|
||||
}
|
||||
if(this.init.area[1] !== 'auto'){
|
||||
boxcss += 'height: ' + this.init.area[1] + ';'
|
||||
}
|
||||
|
||||
layBox.innerHTML = this.getMenubar()
|
||||
+ '<div class="layer-content do-fn-cl '
|
||||
+ (this.init.icon === 0 && 'none-icon' || '')
|
||||
+ '" style="'
|
||||
+ boxcss
|
||||
+ '">'
|
||||
+ this.getCont()
|
||||
+ '</div>'
|
||||
+ this.getBtns()
|
||||
+ (this.init.type === 5 && '<i class="arrow" style="border-top-color: '
|
||||
+ this.init.background
|
||||
+ '"></i>' || '')
|
||||
|
||||
return [this.init.shade ? coverBox : null, layBox]
|
||||
},
|
||||
getCont: function(){
|
||||
if(this.init.type === 6){
|
||||
return this.getLoading(this.init.load)
|
||||
}else{
|
||||
return this.getIcon()
|
||||
+ '<div class="detail" :html="content"></div>'
|
||||
}
|
||||
},
|
||||
getLoading: function(style){
|
||||
return '<div class="do-ui-load load-style-'
|
||||
+ style
|
||||
+ '">'
|
||||
+ '<span class="dot-box">'
|
||||
+ reapeat('<i></i>', this.dot[style])
|
||||
+ '</span>'
|
||||
+ '</div>'
|
||||
},
|
||||
//获取窗口导航条
|
||||
getMenubar: function(){
|
||||
var html = ''
|
||||
if(this.init.menubar){
|
||||
html += '<div class="layer-title do-fn-noselect" ';
|
||||
//可拖拽
|
||||
if(!this.init.fixed){
|
||||
html += ':drag="do-layer" data-limit="window" '
|
||||
}
|
||||
|
||||
html += '>{{title}}'
|
||||
+ '<a class="action-close deficon" :click="no(\'' + this.init.$id + '\')"></a>'
|
||||
+ '</div>'
|
||||
}
|
||||
return html
|
||||
},
|
||||
//获取窗口内容的图标
|
||||
getIcon: function(){
|
||||
if(this.init.icon === 0){
|
||||
return ''
|
||||
}
|
||||
if(this.init.type < 4 || this.init.type === 5 || this.init.specialMode){
|
||||
return '<span class="deficon icon-' + this.init.icon + '"></span>'
|
||||
}
|
||||
return ''
|
||||
},
|
||||
// 获取窗口按钮
|
||||
getBtns: function(){
|
||||
if(this.init.type > 3){
|
||||
return ''
|
||||
}else{
|
||||
var html = '<div class="layer-btns do-fn-noselect">';
|
||||
if(this.init.type > 1){
|
||||
html += '<a href="javascript:;" class="action-no" '
|
||||
+ ':click="no(\'' + this.init.$id + '\')" '
|
||||
+ ':text="btns[1]"></a>'
|
||||
+ '<a href="javascript:;" class="action-yes" '
|
||||
+ ':click="yes(\'' + this.init.$id + '\')" '
|
||||
+ ':text="btns[0]"></a>'
|
||||
}else{
|
||||
html += '<a href="javascript:;" class="action-yes" '
|
||||
+ ':click="yes(\'' + this.init.$id + '\')" '
|
||||
+ ':text="btns[0]"></a>'
|
||||
}
|
||||
html += '</div>'
|
||||
|
||||
return html
|
||||
}
|
||||
},
|
||||
append: function(){
|
||||
//如果有已经打开的弹窗,则关闭
|
||||
if(unique){
|
||||
__layer.close(unique)
|
||||
}
|
||||
if(this.init.type < 4){
|
||||
unique = this.init.$id
|
||||
}
|
||||
layerDom[this.init.$id] = this.create()
|
||||
if(layerDom[this.init.$id][0]){
|
||||
document.body.appendChild(layerDom[this.init.$id][0])
|
||||
//仅在允许点击遮罩时,初始化控制器,减少资源消耗
|
||||
if(this.init.shadeClose){
|
||||
yua.define(this.cInit)
|
||||
yua.scan(layerDom[this.init.$id][0])
|
||||
}
|
||||
}
|
||||
|
||||
document.body.appendChild(layerDom[this.init.$id][1])
|
||||
yua.define(this.init)
|
||||
yua.scan(layerDom[this.init.$id][1])
|
||||
return this
|
||||
},
|
||||
show: function(){
|
||||
var _this = this;
|
||||
|
||||
setTimeout(function(){
|
||||
var style = {visibility: '', background: _this.init.background},
|
||||
css = getComputedStyle(layerDom[_this.init.$id][1]);
|
||||
|
||||
if(_this.init.type === 5){
|
||||
style.color = _this.init.color
|
||||
|
||||
var $elem = yua(_this.init.$elem),
|
||||
ew = $elem.innerWidth(),
|
||||
ol = $elem.offset().left - document.body.scrollLeft,
|
||||
ot = $elem.offset().top - document.body.scrollTop;
|
||||
|
||||
style.left = ol + (ew * 0.7)
|
||||
style.top = ot - parseInt(css.height) - 8
|
||||
|
||||
}else{
|
||||
if(_this.init.offset){
|
||||
style.top = fixOffset(_this.init.offset[0])
|
||||
style.right = fixOffset(_this.init.offset[1])
|
||||
style.bottom = fixOffset(_this.init.offset[2])
|
||||
style.left = fixOffset(_this.init.offset[3])
|
||||
}else{
|
||||
style = yua.mix(style, {
|
||||
marginLeft: -parseInt(css.width) / 2,
|
||||
marginTop: -parseInt(css.height) / 2,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
yua(layerDom[_this.init.$id][1]).css(style)
|
||||
|
||||
}, 4)
|
||||
|
||||
|
||||
if(this.init.success && typeof this.init.success === 'function'){
|
||||
//弹窗成功的回调
|
||||
this.init.success(this.init.$id)
|
||||
}
|
||||
// loading类型,回调需要自动触发
|
||||
if(this.init.type > 3) {
|
||||
//大于0自动触发超时关闭
|
||||
if(this.init.timeout > 0){
|
||||
clearTimeout(this.timeout)
|
||||
this.timeout = setTimeout(function(){
|
||||
|
||||
clearTimeout(_this.timeout)
|
||||
__layer.close(_this.init.$id)
|
||||
|
||||
// 为loading类型时,自动关闭同时触发回调
|
||||
if(_this.init.type === 6){
|
||||
_this.init.yes(_this.init.$id)
|
||||
}
|
||||
|
||||
}, this.init.timeout)
|
||||
|
||||
} else if(this.init.type === 6) {
|
||||
// loading类型, 非自动关闭时, 主动触发回调
|
||||
this.init.yes(this.init.$id)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
ready: function(conf){
|
||||
this.init = yua.mix({}, defconf, conf)
|
||||
if(!this.init.$id){
|
||||
this.init.$id = uuid();
|
||||
}
|
||||
if(this.init.icon > 17){
|
||||
this.icon.icon = 17
|
||||
}
|
||||
//base版没有iframe类型
|
||||
if(this.init.type === 4){
|
||||
this.icon.type = 7
|
||||
}
|
||||
this.cInit = {
|
||||
$id: this.init.$id + '-c',
|
||||
close: this.init.shadeClose ? close : yua.noop
|
||||
};
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
yua.directive('layer', {
|
||||
priority: 1400,
|
||||
init: function(binding){
|
||||
if(!binding.param){
|
||||
binding.element.style.display = 'none'
|
||||
}
|
||||
},
|
||||
update: function(val){
|
||||
if(!val){
|
||||
return console.error(new Error(':layer指令格式不正确或无效属性. [' + this.name + '="' + this.expr) + '"]')
|
||||
}
|
||||
|
||||
var _this = this,
|
||||
init = Object.assign({}, this.element.dataset);
|
||||
|
||||
if(!this.param){
|
||||
init.type = 7;
|
||||
init.$id = '$wrap-' + val;
|
||||
if(!init.hasOwnProperty('menubar')){
|
||||
init.menubar = false;
|
||||
}
|
||||
|
||||
var tmp = new __constructor().ready(init);
|
||||
|
||||
tmp.init.content = this.element.cloneNode(true);
|
||||
|
||||
layerObj[tmp.init.$id] = {obj: tmp, parentElem: this.element.parentNode, wrap: this.element, show: false};
|
||||
layerDom[tmp.init.$id] = tmp.create();
|
||||
}else if(this.param === 'tips'){
|
||||
var $elem = yua(this.element),
|
||||
ew = $elem.innerWidth(),
|
||||
ol = $elem.offset().left - document.body.scrollLeft,
|
||||
ot = $elem.offset().top - document.body.scrollTop,
|
||||
tipsBox = document.createElement('div'),
|
||||
tipsArrow = document.createElement('i'),
|
||||
tipsCont = document.createElement('div');
|
||||
|
||||
|
||||
tipsBox.className = 'do-layer skin-def type-5'
|
||||
tipsBox.style.left = ol + (ew * 0.7) + 'px'
|
||||
if(init.background){
|
||||
tipsBox.style.background = init.background
|
||||
tipsArrow.style.borderTopColor = init.background
|
||||
}
|
||||
if(init.color){
|
||||
tipsBox.style.color = init.color
|
||||
}
|
||||
tipsCont.className = 'layer-content'
|
||||
tipsCont.textContent = val
|
||||
tipsArrow.className = 'arrow'
|
||||
tipsBox.appendChild(tipsCont)
|
||||
tipsBox.appendChild(tipsArrow)
|
||||
|
||||
|
||||
|
||||
yua(document).bind('scroll', function(){
|
||||
ol = $elem.offset().left - document.body.scrollLeft;
|
||||
ot = $elem.offset().top - document.body.scrollTop;
|
||||
|
||||
tipsBox.style.left = ol + (ew * 0.7) + 'px'
|
||||
tipsBox.style.top = (ot - tipsBox.offsetHeight - 8) + 'px'
|
||||
})
|
||||
|
||||
$elem.bind('mouseenter', function(ev){
|
||||
_this.element.parentNode.appendChild(tipsBox)
|
||||
clearTimeout(_this.showTime)
|
||||
clearTimeout(_this.hideTime)
|
||||
_this.showTime = setTimeout(function(){
|
||||
tipsBox.style.top = (ot - tipsBox.offsetHeight - 8) + 'px'
|
||||
tipsBox.classList.add('active')
|
||||
|
||||
}, 4)
|
||||
|
||||
})
|
||||
$elem.bind('mouseleave', function(){
|
||||
_this.hideTime = setTimeout(function(){
|
||||
clearTimeout(_this.hideTime)
|
||||
try{
|
||||
_this.element.parentNode.removeChild(tipsBox)
|
||||
}catch(err){}
|
||||
}, 150)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
if(!window.layer)
|
||||
window.layer = __layer
|
||||
|
||||
|
||||
return __layer
|
||||
|
||||
})
|
|
@ -6,22 +6,28 @@
|
|||
* @version $Id$
|
||||
*/
|
||||
|
||||
@import "../../../../css/var.scss";
|
||||
@import "var.scss";
|
||||
|
||||
|
||||
.do-layer {position:fixed;left:50%;top:50%;z-index:65535;width:auto;height:auto;
|
||||
.do-layer {width:auto;height:auto;
|
||||
|
||||
&.mask {position:fixed;z-index:65534;left:0;top:0;width:100%;height:100%;background:rgba(0,0,0,.3);}
|
||||
|
||||
a {text-decoration:none;}
|
||||
|
||||
/* 默认皮肤 */
|
||||
&.skin-def {color:#666;font-size:14px;box-shadow:0 0 10px rgba(0,0,0,.3);
|
||||
.layer-box {position:absolute;left:50%;top:50%;z-index:65535;
|
||||
|
||||
.icon-0::before {content:"\e62e";color:nth($cr, 1);} // question
|
||||
&.scale {transform:scale(1.02);transition:transform .1s linear;}
|
||||
|
||||
/* 默认皮肤 */
|
||||
&.skin-def {padding:15px 10px;border-radius:3px;color:#666;font-size:14px;box-shadow:0 5px 20px rgba(0,0,0,.3);
|
||||
|
||||
.icon-0::before {content:"\e674";color:nth($cr, 1);} // question
|
||||
.icon-1::before {content:"\e610";color:nth($ct, 1);} // get
|
||||
.icon-2::before {content:"\e6f8";color:nth($cb, 1);} // happy
|
||||
.icon-3::before {content:"\e6fd";color:nth($co, 1);} // sad
|
||||
.icon-4::before {content:"\e6f6";color:nth($co, 1);} // warn
|
||||
.icon-5::before {content:"\e630";color:nth($ct, 1);} // face
|
||||
.icon-5::before {content:"\e673";color:nth($ct, 1);} // face
|
||||
.icon-6::before {content:"\e636";color:nth($cgr, 1);} // time
|
||||
.icon-7::before {content:"\e623";color:nth($co, 1);} // star
|
||||
.icon-8::before {content:"\e604";color:nth($cr, 1);} // mute
|
||||
|
@ -29,25 +35,13 @@
|
|||
|
||||
|
||||
/* 弹层标题栏 */
|
||||
.layer-title {width:100%;height:43px;padding:0 8px;line-height:43px;background:#f5f5f5;font-size:16px;color:nth($cgr, 1);}
|
||||
|
||||
.action-min,
|
||||
.action-close {position:absolute;display:block;top:12px;width:20px;height:20px;line-height:20px;font-size:14px;text-align:center;cursor:pointer;color:nth($cgr, 2);
|
||||
|
||||
&:hover {color:nth($ct, 1);}
|
||||
}
|
||||
.action-min {right:40px;
|
||||
&::before {content:"\e634"}
|
||||
}
|
||||
.action-close {right:10px;
|
||||
&::before {content:"\e687"}
|
||||
}
|
||||
.layer-title {width:100%;height:43px;padding:0 10px;line-height:43px;font-size:16px;color:nth($cgr, 1);}
|
||||
|
||||
/* 弹层主体内容 */
|
||||
.layer-content {position:relative;width:100%;height:auto;min-height:50px;padding:10px;
|
||||
|
||||
.msg-icon {position:absolute;left:10px;top:10px;width:50px;height:auto;line-height:40px;font-size:35px;text-align:center;}
|
||||
.detail {width:auto;height:100%;margin:auto auto auto 60px;padding:5px 15px;word-break:break-all;word-wrap: break-word;
|
||||
.detail {width:auto;height:100%;margin:auto auto auto 50px;padding:5px 15px;word-break:break-all;word-wrap: break-word;
|
||||
|
||||
.prompt-value {width: 230px;height: 30px;padding: 0 8px;border: 1px solid #ddd;border-radius: 3px;
|
||||
|
||||
|
@ -62,12 +56,16 @@
|
|||
|
||||
|
||||
/* 弹层按钮部分 */
|
||||
.layer-btns {width:100%;height:40px;padding:0 5px;line-height:30px;font-size:14px;color:#454545;text-align:right;
|
||||
.layer-ctrl {width:100%;height:40px;padding:5px 0;line-height:30px;font-size:14px;color:#454545;text-align:right;
|
||||
|
||||
a {display:inline-block;width:auto;min-width:60px;height:30px;margin:0 5px;padding:0 10px;color:nth($cgr, 1);text-align:center;background:nth($cp, 1);@include ts();
|
||||
a {overflow:hidden;position:relative;display:inline-block;width:auto;min-width:60px;height:30px;margin-left:5px;padding:0 10px;color:nth($ct, 1);text-align:center;
|
||||
|
||||
&:hover {background:nth($cp, 2)}
|
||||
&:active {background:nth($cp, 3)}
|
||||
&::before {position:absolute;left:-50%;top:-50%;z-index:-1;display:block;width:200%;height:200%;border-radius:50%;background:nth($cp, 2); content:"";opacity:0;transform: scale(0, .0); transition:opacity 1.3s cubic-bezier(0.23, 1, 0.32, 1),transform 1.3s cubic-bezier(0.23, 1, 0.32, 1);}
|
||||
|
||||
&:hover {
|
||||
&::before {opacity:1;transform:scale(1, .8);}
|
||||
}
|
||||
&:active {background:nth($cp, 1)}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,7 +74,7 @@
|
|||
/* ;alert/confirm/prompt 3类弹层 */
|
||||
&.type-1,
|
||||
&.type-2,
|
||||
&.type-3 {max-width:600px;min-width:230px;}
|
||||
&.type-3 {max-width:600px;min-width:300px;}
|
||||
|
||||
|
||||
/* tips类弹层(type 5) */
|
||||
|
@ -178,9 +176,15 @@
|
|||
|
||||
&:active {z-index:65536;}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
.do-layer-cover {position:fixed;left:0;top:0;z-index:65534;width:100%;height:100%;background:rgba(255,255,255,.05);
|
||||
.do-layer-cover {
|
||||
|
||||
&.type-6 {background:rgba(0,0,0,.3);}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -5,101 +5,107 @@
|
|||
*
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
'use strict'
|
||||
import 'layer/base'
|
||||
|
||||
define(['lib/layer/base'], function(){
|
||||
|
||||
function objArr(num){
|
||||
function objArr(num) {
|
||||
var arr = []
|
||||
while(num > 0){
|
||||
arr.push({v: 0})
|
||||
while (num > 0) {
|
||||
arr.push({ v: 0 })
|
||||
num--
|
||||
}
|
||||
return arr
|
||||
}
|
||||
function trim(str, sign){
|
||||
}
|
||||
function trim(str, sign) {
|
||||
return str.replace(new RegExp('^' + sign + '|' + sign + '$', 'g'), '')
|
||||
}
|
||||
function getOrderArr(len){
|
||||
var arr = [], i = 0;
|
||||
while(i < len){
|
||||
}
|
||||
function getOrderArr(len) {
|
||||
var arr = [],
|
||||
i = 0
|
||||
while (i < len) {
|
||||
arr.push(i++)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
ME.addon = {
|
||||
h1: function(elem, vm){
|
||||
var offset = yua(elem).offset(),
|
||||
}
|
||||
const addon = {
|
||||
h1: function(elem, vm) {
|
||||
var offset = Anot(elem).offset(),
|
||||
wrap = ME.selection(vm.$editor, true) || '在此输入文本',
|
||||
h1ID = layer.open({
|
||||
type: 7,
|
||||
menubar: false,
|
||||
shadeClose: true,
|
||||
fixed: true,
|
||||
$insert: function(level){
|
||||
$insert: function(level) {
|
||||
wrap = wrap.replace(/^#{1,6} /, '')
|
||||
wrap = ME.repeat('#', level) + ' ' + wrap
|
||||
ME.insert(vm.$editor, wrap, true)
|
||||
layer.close(h1ID)
|
||||
},
|
||||
offset: [offset.top + 37 - ME.doc.scrollTop(), 'auto', 'auto', offset.left - ME.doc.scrollLeft()],
|
||||
content: '<ul class="do-meditor-h1 do-fn-noselect do-meditor-font">'
|
||||
+ '<li :click="$insert(1)" class="h1">一级标题</li>'
|
||||
+ '<li :click="$insert(2)" class="h2">二级标题</li>'
|
||||
+ '<li :click="$insert(3)" class="h3">三级标题</li>'
|
||||
+ '<li :click="$insert(4)" class="h4">四级标题</li>'
|
||||
+ '<li :click="$insert(5)" class="h5">五级标题</li>'
|
||||
+ '<li :click="$insert(6)" class="h6">六级标题</li>'
|
||||
+ '</ul>'
|
||||
offset: [
|
||||
offset.top + 37 - ME.doc.scrollTop(),
|
||||
'auto',
|
||||
'auto',
|
||||
offset.left - ME.doc.scrollLeft()
|
||||
],
|
||||
content:
|
||||
'<ul class="do-meditor-h1 do-fn-noselect do-meditor-font">' +
|
||||
'<li :click="$insert(1)" class="h1">一级标题</li>' +
|
||||
'<li :click="$insert(2)" class="h2">二级标题</li>' +
|
||||
'<li :click="$insert(3)" class="h3">三级标题</li>' +
|
||||
'<li :click="$insert(4)" class="h4">四级标题</li>' +
|
||||
'<li :click="$insert(5)" class="h5">五级标题</li>' +
|
||||
'<li :click="$insert(6)" class="h6">六级标题</li>' +
|
||||
'</ul>'
|
||||
})
|
||||
},
|
||||
quote: function(elem, vm){
|
||||
quote: function(elem, vm) {
|
||||
var wrap = ME.selection(vm.$editor) || '在此输入文本'
|
||||
wrap = '> ' + wrap
|
||||
|
||||
ME.insert(vm.$editor, wrap, true)
|
||||
},
|
||||
bold: function(elem, vm){
|
||||
bold: function(elem, vm) {
|
||||
var wrap = ME.selection(vm.$editor) || '在此输入文本',
|
||||
wraped = trim(wrap, '\\*\\*')
|
||||
|
||||
wrap = wrap === wraped ? ('**' + wrap + '**') : wraped
|
||||
wrap = wrap === wraped ? '**' + wrap + '**' : wraped
|
||||
|
||||
ME.insert(vm.$editor, wrap, true)
|
||||
},
|
||||
italic: function(elem, vm){
|
||||
italic: function(elem, vm) {
|
||||
var wrap = ME.selection(vm.$editor) || '在此输入文本',
|
||||
wraped = trim(wrap, '_')
|
||||
|
||||
wrap = wrap === wraped ? ('_' + wrap + '_') : wraped
|
||||
wrap = wrap === wraped ? '_' + wrap + '_' : wraped
|
||||
|
||||
ME.insert(vm.$editor, wrap, true)
|
||||
},
|
||||
through: function(elem, vm){
|
||||
through: function(elem, vm) {
|
||||
var wrap = ME.selection(vm.$editor) || '在此输入文本',
|
||||
wraped = trim(wrap, '~~')
|
||||
|
||||
wrap = wrap === wraped ? ('~~' + wrap + '~~') : wraped
|
||||
wrap = wrap === wraped ? '~~' + wrap + '~~' : wraped
|
||||
|
||||
ME.insert(vm.$editor, wrap, true)
|
||||
},
|
||||
unordered: function(elem, vm){
|
||||
unordered: function(elem, vm) {
|
||||
var wrap = ME.selection(vm.$editor) || '在此输入文本'
|
||||
wrap = '* ' + wrap
|
||||
|
||||
ME.insert(vm.$editor, wrap, false)
|
||||
},
|
||||
ordered: function(elem, vm){
|
||||
ordered: function(elem, vm) {
|
||||
var wrap = ME.selection(vm.$editor) || '在此输入文本'
|
||||
wrap = '1. ' + wrap
|
||||
|
||||
ME.insert(vm.$editor, wrap, false)
|
||||
},
|
||||
hr: function(elem, vm){
|
||||
hr: function(elem, vm) {
|
||||
ME.insert(vm.$editor, '\n\n---\n\n', false)
|
||||
},
|
||||
link: function(elem, vm){
|
||||
var offset = yua(elem).offset(),
|
||||
link: function(elem, vm) {
|
||||
var offset = Anot(elem).offset(),
|
||||
wrap = ME.selection(vm.$editor) || '',
|
||||
layid = layer.open({
|
||||
type: 7,
|
||||
|
@ -109,41 +115,50 @@ define(['lib/layer/base'], function(){
|
|||
link: '',
|
||||
linkName: wrap,
|
||||
linkTarget: 1,
|
||||
$confirm: function(){
|
||||
var lvm = yua.vmodels[layid]
|
||||
if(!lvm.link || !lvm.linkName){
|
||||
$confirm: function() {
|
||||
var lvm = Anot.vmodels[layid]
|
||||
if (!lvm.link || !lvm.linkName) {
|
||||
return layer.alert('链接文字和地址不能为空')
|
||||
}
|
||||
var val = '[' + lvm.linkName + ']('
|
||||
+ lvm.link
|
||||
+ (lvm.linkTarget === 1 ? ' "target=_blank"' : '')
|
||||
+ ')'
|
||||
var val =
|
||||
'[' +
|
||||
lvm.linkName +
|
||||
'](' +
|
||||
lvm.link +
|
||||
(lvm.linkTarget === 1 ? ' "target=_blank"' : '') +
|
||||
')'
|
||||
ME.insert(vm.$editor, val, false)
|
||||
layer.close(layid)
|
||||
},
|
||||
offset: [offset.top + 37 - ME.doc.scrollTop(), 'auto', 'auto', offset.left - ME.doc.scrollLeft()],
|
||||
content: '<div class="do-meditor-common do-meditor-font">'
|
||||
+ '<section class="input"><span class="label">链接文字</span>'
|
||||
+ '<input class="txt" :duplex="linkName" />'
|
||||
+ '</section>'
|
||||
+ '<section class="input"><span class="label">链接地址</span>'
|
||||
+ '<input class="txt" :duplex="link"/>'
|
||||
+ '</section>'
|
||||
+ '<section>'
|
||||
+ '<label><input name="link" type="radio" class="radio" :duplex-number="linkTarget" value="1"/> 新窗口打开</label>'
|
||||
+ '<label><input name="link" type="radio" class="radio" :duplex-number="linkTarget" value="2"/> 本窗口打开</label>'
|
||||
+ '</section>'
|
||||
+ '<section>'
|
||||
+ '<a href="javascript:;" class="submit" :click="$confirm">确定</a>'
|
||||
+ '</section>'
|
||||
+ '</div>'
|
||||
offset: [
|
||||
offset.top + 37 - ME.doc.scrollTop(),
|
||||
'auto',
|
||||
'auto',
|
||||
offset.left - ME.doc.scrollLeft()
|
||||
],
|
||||
content:
|
||||
'<div class="do-meditor-common do-meditor-font">' +
|
||||
'<section class="input"><span class="label">链接文字</span>' +
|
||||
'<input class="txt" :duplex="linkName" />' +
|
||||
'</section>' +
|
||||
'<section class="input"><span class="label">链接地址</span>' +
|
||||
'<input class="txt" :duplex="link"/>' +
|
||||
'</section>' +
|
||||
'<section>' +
|
||||
'<label><input name="link" type="radio" class="radio" :duplex-number="linkTarget" value="1"/> 新窗口打开</label>' +
|
||||
'<label><input name="link" type="radio" class="radio" :duplex-number="linkTarget" value="2"/> 本窗口打开</label>' +
|
||||
'</section>' +
|
||||
'<section>' +
|
||||
'<a href="javascript:;" class="submit" :click="$confirm">确定</a>' +
|
||||
'</section>' +
|
||||
'</div>'
|
||||
})
|
||||
},
|
||||
time: function(elem, vm){
|
||||
time: function(elem, vm) {
|
||||
ME.insert(vm.$editor, new Date().format(), false)
|
||||
},
|
||||
face: function(elem, vm){
|
||||
var offset = yua(elem).offset(),
|
||||
face: function(elem, vm) {
|
||||
var offset = Anot(elem).offset(),
|
||||
faceid = 0,
|
||||
layid = layer.open({
|
||||
type: 7,
|
||||
|
@ -151,67 +166,86 @@ define(['lib/layer/base'], function(){
|
|||
fixed: true,
|
||||
shadeClose: true,
|
||||
arr: getOrderArr(36),
|
||||
offset: [offset.top + 37 - ME.doc.scrollTop(), 'auto', 'auto', offset.left - ME.doc.scrollLeft()],
|
||||
content: '<ul class="do-meditor-face">'
|
||||
+ '<li class="item" :repeat="arr" ><img :attr-src="ME.path + \'/addon/face/\' + el + \'.gif\'" :click="$insert(this.src)" /></li>'
|
||||
+ '</ul>',
|
||||
$insert: function(src){
|
||||
offset: [
|
||||
offset.top + 37 - ME.doc.scrollTop(),
|
||||
'auto',
|
||||
'auto',
|
||||
offset.left - ME.doc.scrollLeft()
|
||||
],
|
||||
content:
|
||||
'<ul class="do-meditor-face">' +
|
||||
'<li class="item" :repeat="arr" ><img :attr-src="ME.path + \'/addon/face/\' + el + \'.gif\'" :click="$insert(this.src)" /></li>' +
|
||||
'</ul>',
|
||||
$insert: function(src) {
|
||||
ME.insert(vm.$editor, '![](' + src + ')', false)
|
||||
layer.close(layid)
|
||||
}
|
||||
})
|
||||
},
|
||||
table: function(elem, vm){
|
||||
var offset = yua(elem).offset();
|
||||
table: function(elem, vm) {
|
||||
var offset = Anot(elem).offset()
|
||||
layer.open({
|
||||
type: 7,
|
||||
title: '0行 x 0列',
|
||||
fixed: true,
|
||||
shadeClose: true,
|
||||
offset: [offset.top + 37 - ME.doc.scrollTop(), 'auto', 'auto', offset.left - ME.doc.scrollLeft()],
|
||||
matrix: objArr(10).map(function(){return objArr(10)}),
|
||||
content: '<ul class="do-meditor-table">'
|
||||
+ '<li :repeat="matrix"><span :repeat-o="el" :class="{active: o.v}" :data="{x: $index, y: $outer.$index}"></span></li>'
|
||||
+ '</ul>',
|
||||
success: function(id){
|
||||
offset: [
|
||||
offset.top + 37 - ME.doc.scrollTop(),
|
||||
'auto',
|
||||
'auto',
|
||||
offset.left - ME.doc.scrollLeft()
|
||||
],
|
||||
matrix: objArr(10).map(function() {
|
||||
return objArr(10)
|
||||
}),
|
||||
content:
|
||||
'<ul class="do-meditor-table">' +
|
||||
'<li :repeat="matrix"><span :repeat-o="el" :class="{active: o.v}" :data="{x: $index, y: $outer.$index}"></span></li>' +
|
||||
'</ul>',
|
||||
success: function(id) {
|
||||
var tb = document.querySelector('.do-meditor-table'),
|
||||
_this = yua.vmodels[id],
|
||||
lastx,lasty;
|
||||
yua(tb).bind('mousemove', function(ev){
|
||||
if(ev.target.nodeName === 'SPAN'){
|
||||
_this = Anot.vmodels[id],
|
||||
lastx,
|
||||
lasty
|
||||
Anot(tb).bind('mousemove', function(ev) {
|
||||
if (ev.target.nodeName === 'SPAN') {
|
||||
var x = ev.target.dataset.x - 0,
|
||||
y = ev.target.dataset.y - 0;
|
||||
if(x === lastx && y === lasty){
|
||||
y = ev.target.dataset.y - 0
|
||||
if (x === lastx && y === lasty) {
|
||||
return
|
||||
}
|
||||
lastx = x;
|
||||
lasty = y;
|
||||
_this.title = (y + 1) + '行 x ' + (x + 1) + '列'
|
||||
for(var i = 0; i <= 9; i++){
|
||||
for(var j = 0; j <= 9; j++){
|
||||
_this.matrix[i][j].v = (i <= y && j <= x) ? 1 : 0
|
||||
lastx = x
|
||||
lasty = y
|
||||
_this.title = y + 1 + '行 x ' + (x + 1) + '列'
|
||||
for (var i = 0; i <= 9; i++) {
|
||||
for (var j = 0; j <= 9; j++) {
|
||||
_this.matrix[i][j].v = i <= y && j <= x ? 1 : 0
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
yua(tb).bind('mouseleave', function(ev){
|
||||
lastx = -1;
|
||||
lasty = -1;
|
||||
Anot(tb).bind('mouseleave', function(ev) {
|
||||
lastx = -1
|
||||
lasty = -1
|
||||
_this.title = '0行 x 0列'
|
||||
for(var i = 0; i <= 9; i++){
|
||||
for(var j = 0; j <= 9; j++){
|
||||
for (var i = 0; i <= 9; i++) {
|
||||
for (var j = 0; j <= 9; j++) {
|
||||
_this.matrix[i][j].v = 0
|
||||
}
|
||||
}
|
||||
})
|
||||
yua(tb).bind('click', function(ev){
|
||||
if(ev.target.nodeName === 'SPAN'){
|
||||
Anot(tb).bind('click', function(ev) {
|
||||
if (ev.target.nodeName === 'SPAN') {
|
||||
var x = ev.target.dataset.x - 0 + 1,
|
||||
y = ev.target.dataset.y - 0 + 1;
|
||||
y = ev.target.dataset.y - 0 + 1
|
||||
|
||||
var val = '\n\n' + ME.repeat('| 表头 ', x) + '|\n'
|
||||
+ ME.repeat('| -- ', x) + '|\n'
|
||||
+ ME.repeat(ME.repeat('| ', x) + '|\n', y)
|
||||
var val =
|
||||
'\n\n' +
|
||||
ME.repeat('| 表头 ', x) +
|
||||
'|\n' +
|
||||
ME.repeat('| -- ', x) +
|
||||
'|\n' +
|
||||
ME.repeat(ME.repeat('| ', x) + '|\n', y)
|
||||
ME.insert(vm.$editor, val, false)
|
||||
layer.close(id)
|
||||
}
|
||||
|
@ -219,8 +253,8 @@ define(['lib/layer/base'], function(){
|
|||
}
|
||||
})
|
||||
},
|
||||
image: function(elem, vm){
|
||||
var offset = yua(elem).offset(),
|
||||
image: function(elem, vm) {
|
||||
var offset = Anot(elem).offset(),
|
||||
wrap = ME.selection(vm.$editor) || '',
|
||||
layid = layer.open({
|
||||
type: 7,
|
||||
|
@ -229,9 +263,9 @@ define(['lib/layer/base'], function(){
|
|||
fixed: true,
|
||||
img: '',
|
||||
imgAlt: wrap,
|
||||
$confirm: function(){
|
||||
var lvm = yua.vmodels[layid]
|
||||
if(!lvm.img || !lvm.imgAlt){
|
||||
$confirm: function() {
|
||||
var lvm = Anot.vmodels[layid]
|
||||
if (!lvm.img || !lvm.imgAlt) {
|
||||
return layer.alert('图片描述和图片地址不能为空')
|
||||
}
|
||||
var val = '![' + lvm.imgAlt + '](' + lvm.img + ')'
|
||||
|
@ -239,125 +273,135 @@ define(['lib/layer/base'], function(){
|
|||
ME.insert(vm.$editor, val, false)
|
||||
layer.close(layid)
|
||||
},
|
||||
offset: [offset.top + 37 - ME.doc.scrollTop(), 'auto', 'auto', offset.left - ME.doc.scrollLeft()],
|
||||
content: '<div class="do-meditor-common do-meditor-font">'
|
||||
+ '<section class="input"><span class="label">图片描述</span>'
|
||||
+ '<input class="txt" :duplex="imgAlt" />'
|
||||
+ '</section>'
|
||||
+ '<section class="input"><span class="label">图片地址</span>'
|
||||
+ '<input class="txt" :duplex="img"/>'
|
||||
+ '</section>'
|
||||
+ '<section>'
|
||||
+ '<a href="javascript:;" class="submit" :click="$confirm">确定</a>'
|
||||
+ '</section>'
|
||||
+ '</div>'
|
||||
offset: [
|
||||
offset.top + 37 - ME.doc.scrollTop(),
|
||||
'auto',
|
||||
'auto',
|
||||
offset.left - ME.doc.scrollLeft()
|
||||
],
|
||||
content:
|
||||
'<div class="do-meditor-common do-meditor-font">' +
|
||||
'<section class="input"><span class="label">图片描述</span>' +
|
||||
'<input class="txt" :duplex="imgAlt" />' +
|
||||
'</section>' +
|
||||
'<section class="input"><span class="label">图片地址</span>' +
|
||||
'<input class="txt" :duplex="img"/>' +
|
||||
'</section>' +
|
||||
'<section>' +
|
||||
'<a href="javascript:;" class="submit" :click="$confirm">确定</a>' +
|
||||
'</section>' +
|
||||
'</div>'
|
||||
})
|
||||
},
|
||||
file: function(elem, vm){
|
||||
file: function(elem, vm) {
|
||||
this.link(elem, vm, false)
|
||||
},
|
||||
inlinecode: function(elem, vm){
|
||||
inlinecode: function(elem, vm) {
|
||||
var wrap = ME.selection(vm.$editor) || '在此输入文本',
|
||||
wraped = trim(wrap, '`');
|
||||
wraped = trim(wrap, '`')
|
||||
|
||||
wrap = wrap === wraped ? ('`' + wrap + '`') : wraped
|
||||
wrap = wrap === wraped ? '`' + wrap + '`' : wraped
|
||||
ME.insert(vm.$editor, wrap, true)
|
||||
},
|
||||
blockcode: function(elem, vm){
|
||||
blockcode: function(elem, vm) {
|
||||
var layid = layer.open({
|
||||
type: 7,
|
||||
title: '添加代码块',
|
||||
$lang: [
|
||||
{id: 'asp'},
|
||||
{id: 'actionscript', name: 'ActionScript(3.0)/Flash/Flex'},
|
||||
{id: 'bash', name: 'Bash/Shell/Bat'},
|
||||
{id: 'css'},
|
||||
{id: 'c', name: 'C'},
|
||||
{id: 'cpp', name: 'C++'},
|
||||
{id: 'csharp', name: 'C#'},
|
||||
{id: 'coffeescript', name: 'CoffeeScript'},
|
||||
{id: 'd', name: 'D'},
|
||||
{id: 'dart'},
|
||||
{id: 'delphi', name: 'Delphi/Pascal'},
|
||||
{id: 'erlang'},
|
||||
{id: 'go', name: 'Golang'},
|
||||
{id: 'html'},
|
||||
{id: 'java'},
|
||||
{id: 'javascript'},
|
||||
{id: 'json'},
|
||||
{id: 'lua'},
|
||||
{id: 'less'},
|
||||
{id: 'markdown'},
|
||||
{id: 'nginx'},
|
||||
{id: 'objective-c'},
|
||||
{id: 'php'},
|
||||
{id: 'perl'},
|
||||
{id: 'python'},
|
||||
{id: 'r', name: 'R'},
|
||||
{id: 'ruby'},
|
||||
{id: 'sql'},
|
||||
{id: 'sass', name: 'SASS/SCSS'},
|
||||
{id: 'swift'},
|
||||
{id: 'typescript'},
|
||||
{id: 'xml'},
|
||||
{id: 'yaml'},
|
||||
{id: 'other', name: '其他语言'},
|
||||
{ id: 'asp' },
|
||||
{ id: 'actionscript', name: 'ActionScript(3.0)/Flash/Flex' },
|
||||
{ id: 'bash', name: 'Bash/Shell/Bat' },
|
||||
{ id: 'css' },
|
||||
{ id: 'c', name: 'C' },
|
||||
{ id: 'cpp', name: 'C++' },
|
||||
{ id: 'csharp', name: 'C#' },
|
||||
{ id: 'coffeescript', name: 'CoffeeScript' },
|
||||
{ id: 'd', name: 'D' },
|
||||
{ id: 'dart' },
|
||||
{ id: 'delphi', name: 'Delphi/Pascal' },
|
||||
{ id: 'erlang' },
|
||||
{ id: 'go', name: 'Golang' },
|
||||
{ id: 'html' },
|
||||
{ id: 'java' },
|
||||
{ id: 'javascript' },
|
||||
{ id: 'json' },
|
||||
{ id: 'lua' },
|
||||
{ id: 'less' },
|
||||
{ id: 'markdown' },
|
||||
{ id: 'nginx' },
|
||||
{ id: 'objective-c' },
|
||||
{ id: 'php' },
|
||||
{ id: 'perl' },
|
||||
{ id: 'python' },
|
||||
{ id: 'r', name: 'R' },
|
||||
{ id: 'ruby' },
|
||||
{ id: 'sql' },
|
||||
{ id: 'sass', name: 'SASS/SCSS' },
|
||||
{ id: 'swift' },
|
||||
{ id: 'typescript' },
|
||||
{ id: 'xml' },
|
||||
{ id: 'yaml' },
|
||||
{ id: 'other', name: '其他语言' }
|
||||
],
|
||||
lang: 'javascript',
|
||||
code: '',
|
||||
$confirm: function(){
|
||||
var lvm = yua.vmodels[layid]
|
||||
var val = '\n```' + lvm.lang + '\n' + (lvm.code || '//在此输入代码') + '\n```\n'
|
||||
$confirm: function() {
|
||||
var lvm = Anot.vmodels[layid]
|
||||
var val =
|
||||
'\n```' + lvm.lang + '\n' + (lvm.code || '//在此输入代码') + '\n```\n'
|
||||
|
||||
ME.insert(vm.$editor, val, false)
|
||||
layer.close(layid)
|
||||
},
|
||||
content: '<div class="do-meditor-codeblock do-meditor-font">'
|
||||
+ '<section class="do-fn-cl"><span class="label">语言类型</span>'
|
||||
+ '<select :duplex="lang">'
|
||||
+ '<option :repeat="$lang" :attr-value="el.id">{{el.name || el.id}}</option>'
|
||||
+ '</select>'
|
||||
+ '</section>'
|
||||
+ '<section>'
|
||||
+ '<textarea :duplex="code" placeholder="在这里输入/粘贴代码"></textarea>'
|
||||
+ '</section>'
|
||||
+ '<section class="do-fn-cl">'
|
||||
+ '<a href="javascript:;" class="submit" :click="$confirm">确定</a>'
|
||||
+ '</section>'
|
||||
+ '</div>'
|
||||
content:
|
||||
'<div class="do-meditor-codeblock do-meditor-font">' +
|
||||
'<section class="do-fn-cl"><span class="label">语言类型</span>' +
|
||||
'<select :duplex="lang">' +
|
||||
'<option :repeat="$lang" :attr-value="el.id">{{el.name || el.id}}</option>' +
|
||||
'</select>' +
|
||||
'</section>' +
|
||||
'<section>' +
|
||||
'<textarea :duplex="code" placeholder="在这里输入/粘贴代码"></textarea>' +
|
||||
'</section>' +
|
||||
'<section class="do-fn-cl">' +
|
||||
'<a href="javascript:;" class="submit" :click="$confirm">确定</a>' +
|
||||
'</section>' +
|
||||
'</div>'
|
||||
})
|
||||
},
|
||||
preview: function(elem, vm){
|
||||
preview: function(elem, vm) {
|
||||
vm.preview = !vm.preview
|
||||
if(vm.preview){
|
||||
if (vm.preview) {
|
||||
vm.htmlTxt = vm.$htmlTxt
|
||||
}
|
||||
},
|
||||
fullscreen: function(elem, vm){
|
||||
fullscreen: function(elem, vm) {
|
||||
vm.fullscreen = !vm.fullscreen
|
||||
vm.$onFullscreen(vm.fullscreen)
|
||||
},
|
||||
about: function(elem){
|
||||
var offset = yua(elem).offset()
|
||||
about: function(elem) {
|
||||
var offset = Anot(elem).offset()
|
||||
layer.open({
|
||||
type: 7,
|
||||
title: '关于编辑器',
|
||||
offset: [offset.top + 37 - ME.doc.scrollTop()],
|
||||
content: '<div class="do-meditor-about do-meditor-font">'
|
||||
+ '<pre>'
|
||||
+ ' __ __ _____ _ _ _\n'
|
||||
+ '| \\/ | ____|__| (_) |_ ___ _ __\n'
|
||||
+ '| |\\/| | _| / _` | | __/ _ \\| \'__|\n'
|
||||
+ '| | | | |__| (_| | | || (_) | |\n'
|
||||
+ '|_| |_|_____\\__,_|_|\\__\\___/|_| '
|
||||
+ 'v' + ME.version + '</pre>'
|
||||
+ '<p>开源在线Markdown编辑器</p>'
|
||||
+ '<p><a target="_blank" href="https://doui.cc/product/meditor">https://doui.cc/product/meditor</a></p>'
|
||||
+ '<p>Copyright © 2017 Yutent, The MIT License.</p>'
|
||||
+ '</div>'
|
||||
content:
|
||||
'<div class="do-meditor-about do-meditor-font">' +
|
||||
'<pre>' +
|
||||
' __ __ _____ _ _ _\n' +
|
||||
'| \\/ | ____|__| (_) |_ ___ _ __\n' +
|
||||
"| |\\/| | _| / _` | | __/ _ \\| '__|\n" +
|
||||
'| | | | |__| (_| | | || (_) | |\n' +
|
||||
'|_| |_|_____\\__,_|_|\\__\\___/|_| ' +
|
||||
'v' +
|
||||
ME.version +
|
||||
'</pre>' +
|
||||
'<p>开源在线Markdown编辑器</p>' +
|
||||
'<p><a target="_blank" href="https://doui.cc/product/meditor">https://doui.cc/product/meditor</a></p>' +
|
||||
'<p>Copyright © 2017 Yutent, The MIT License.</p>' +
|
||||
'</div>'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
export default addon
|
||||
|
|
|
@ -0,0 +1,470 @@
|
|||
/**
|
||||
*
|
||||
* @authors yutent (yutent@doui.cc)
|
||||
* @date 2017-04-17 16:37:12
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
import 'prism/base'
|
||||
import 'marked/index'
|
||||
import addon from './addon/base'
|
||||
import './skin/main.scss'
|
||||
|
||||
marked.setOptions({
|
||||
highlight: function(code, lang) {
|
||||
return Prism.highlight(code, Prism.languages[lang])
|
||||
}
|
||||
})
|
||||
var editorVM = []
|
||||
Anot.ui.meditor = '1.0.0'
|
||||
//存放编辑器公共静态资源
|
||||
window.ME = {
|
||||
version: Anot.ui.meditor,
|
||||
toolbar: {
|
||||
//工具栏title
|
||||
pipe: '',
|
||||
h1: '标题',
|
||||
quote: '引用文本',
|
||||
bold: '粗体',
|
||||
italic: '斜体',
|
||||
through: '删除线',
|
||||
unordered: '无序列表',
|
||||
ordered: '有序列表',
|
||||
link: '超链接',
|
||||
hr: '横线',
|
||||
time: '插入当前时间',
|
||||
face: '表情',
|
||||
table: '插入表格',
|
||||
image: '插入图片',
|
||||
file: '插入附件',
|
||||
inlinecode: '行内代码',
|
||||
blockcode: '代码块',
|
||||
preview: '预览',
|
||||
fullscreen: '全屏',
|
||||
about: '关于编辑器'
|
||||
},
|
||||
addon, //已有插件
|
||||
//往文本框中插入内容
|
||||
insert: function(dom, val, isSelect) {
|
||||
if (document.selection) {
|
||||
dom.focus()
|
||||
var range = document.selection.createRange()
|
||||
range.text = val
|
||||
dom.focus()
|
||||
range.moveStart('character', -1)
|
||||
} else if (dom.selectionStart || dom.selectionStart === 0) {
|
||||
var startPos = dom.selectionStart,
|
||||
endPos = dom.selectionEnd,
|
||||
scrollTop = dom.scrollTop
|
||||
|
||||
dom.value =
|
||||
dom.value.slice(0, startPos) +
|
||||
val +
|
||||
dom.value.slice(endPos, dom.value.length)
|
||||
|
||||
dom.selectionStart = isSelect ? startPos : startPos + val.length
|
||||
dom.selectionEnd = startPos + val.length
|
||||
dom.scrollTop = scrollTop
|
||||
dom.focus()
|
||||
} else {
|
||||
dom.value += val
|
||||
dom.focus()
|
||||
}
|
||||
},
|
||||
/**
|
||||
* [selection 获取选中的文本]
|
||||
* @param {[type]} dom [要操作的元素]
|
||||
* @param {[type]} line [是否强制选取整行]
|
||||
*/
|
||||
selection: function(dom, line) {
|
||||
if (document.selection) {
|
||||
return document.selection.createRange().text
|
||||
} else {
|
||||
var startPos = dom.selectionStart,
|
||||
endPos = dom.selectionEnd
|
||||
|
||||
if (endPos) {
|
||||
//强制选择整行
|
||||
if (line) {
|
||||
startPos = dom.value.slice(0, startPos).lastIndexOf('\n')
|
||||
|
||||
var tmpEnd = dom.value.slice(endPos).indexOf('\n')
|
||||
tmpEnd = tmpEnd < 0 ? 0 : tmpEnd
|
||||
|
||||
startPos += 1 //把\n加上
|
||||
endPos += tmpEnd
|
||||
|
||||
dom.selectionStart = startPos
|
||||
dom.selectionEnd = endPos
|
||||
}
|
||||
} else {
|
||||
//强制选择整行
|
||||
if (line) {
|
||||
endPos = dom.value.indexOf('\n')
|
||||
endPos = endPos < 0 ? dom.value.length : endPos
|
||||
dom.selectionEnd = endPos
|
||||
}
|
||||
}
|
||||
return dom.value.slice(startPos, endPos)
|
||||
}
|
||||
},
|
||||
repeat: function(str, num) {
|
||||
if (String.prototype.repeat) {
|
||||
return str.repeat(num)
|
||||
} else {
|
||||
var result = ''
|
||||
while (num > 0) {
|
||||
result += str
|
||||
num--
|
||||
}
|
||||
return result
|
||||
}
|
||||
},
|
||||
get: function(id) {
|
||||
if (id === void 0) {
|
||||
id = editorVM.length - 1
|
||||
}
|
||||
var vm = editorVM[id]
|
||||
if (vm) {
|
||||
return {
|
||||
id: vm.$id,
|
||||
getVal: function() {
|
||||
return vm.plainTxt.trim()
|
||||
},
|
||||
getHtml: function() {
|
||||
return vm.$htmlTxt
|
||||
},
|
||||
setVal: function(txt) {
|
||||
vm.plainTxt = txt || ''
|
||||
},
|
||||
show: function() {
|
||||
vm.editorVisible = true
|
||||
},
|
||||
hide: function() {
|
||||
vm.editorVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
},
|
||||
doc: Anot(document)
|
||||
}
|
||||
//获取真实的引用路径,避免因为不同的目录结构导致加载失败的情况
|
||||
for (var i in Anot.modules) {
|
||||
if (/meditor/.test(i)) {
|
||||
ME.path = i.slice(0, i.lastIndexOf('/'))
|
||||
break
|
||||
}
|
||||
}
|
||||
var elems = {
|
||||
p: function(str, attr, inner) {
|
||||
return inner ? '\n' + inner + '\n' : ''
|
||||
},
|
||||
br: '\n',
|
||||
'h([1-6])': function(str, level, attr, inner) {
|
||||
var h = ME.repeat('#', level)
|
||||
return '\n' + h + ' ' + inner + '\n'
|
||||
},
|
||||
hr: '\n\n___\n\n',
|
||||
a: function(str, attr, inner) {
|
||||
var href = attr.match(attrExp('href')),
|
||||
title = attr.match(attrExp('title')),
|
||||
tar = attr.match(attrExp('target'))
|
||||
|
||||
href = (href && href[1]) || ''
|
||||
title = (title && title[1]) || ''
|
||||
tar = (tar && tar[1]) || '_self'
|
||||
|
||||
href = href === 'javascript:void(0);' ? 'javascript:;' : href
|
||||
|
||||
return (
|
||||
'[' +
|
||||
(inner || href) +
|
||||
'](' +
|
||||
href +
|
||||
' "title=' +
|
||||
title +
|
||||
';target=' +
|
||||
tar +
|
||||
'")'
|
||||
)
|
||||
},
|
||||
em: function(str, attr, inner) {
|
||||
return (inner && '_' + inner + '_') || ''
|
||||
},
|
||||
strong: function(str, attr, inner) {
|
||||
return (inner && '**' + inner + '**') || ''
|
||||
},
|
||||
code: function(str, attr, inner) {
|
||||
return (inner && '`' + inner + '`') || ''
|
||||
},
|
||||
pre: function(str, attr, inner) {
|
||||
return '\n\n```\n' + inner + '\n```\n'
|
||||
},
|
||||
blockquote: function(str, attr, inner) {
|
||||
return '> ' + inner.trim()
|
||||
},
|
||||
img: function(str, attr, inner) {
|
||||
var src = attr.match(attrExp('src')),
|
||||
alt = attr.match(attrExp('alt'))
|
||||
|
||||
src = (src && src[1]) || ''
|
||||
alt = (alt && alt[1]) || ''
|
||||
|
||||
return '![' + alt + '](' + src + ')'
|
||||
}
|
||||
}
|
||||
|
||||
function attrExp(field) {
|
||||
return new RegExp(field + '\\s?=\\s?["\']?([^"\']*)["\']?', 'i')
|
||||
}
|
||||
function tagExp(tag, open) {
|
||||
var exp = ''
|
||||
if (['br', 'hr', 'img'].indexOf(tag) > -1) {
|
||||
exp = '<' + tag + '([^>]*)\\/?>'
|
||||
} else {
|
||||
exp = '<' + tag + '([^>]*)>([\\s\\S]*?)<\\/' + tag + '>'
|
||||
}
|
||||
return new RegExp(exp, 'gi')
|
||||
}
|
||||
function html2md(str) {
|
||||
try {
|
||||
str = decodeURIComponent(str)
|
||||
} catch (err) {}
|
||||
str = str.replace(/\t/g, ' ').replace(/<meta [^>]*>/, '')
|
||||
|
||||
for (var i in elems) {
|
||||
var cb = elems[i],
|
||||
exp = tagExp(i)
|
||||
|
||||
if (i === 'blockquote') {
|
||||
while (str.match(exp)) {
|
||||
str = str.replace(exp, cb)
|
||||
}
|
||||
} else {
|
||||
str = str.replace(exp, cb)
|
||||
}
|
||||
|
||||
if (i === 'em') {
|
||||
exp = tagExp('i')
|
||||
str = str.replace(exp, cb)
|
||||
}
|
||||
if (i === 'strong') {
|
||||
exp = tagExp('b')
|
||||
str = str.replace(exp, cb)
|
||||
}
|
||||
}
|
||||
var liExp = /<(ul|ol)[^>]*>(?:(?!<ul|<ol)[\s\S])*?<\/\1>/gi
|
||||
while (str.match(liExp)) {
|
||||
str = str.replace(liExp, function(match) {
|
||||
match = match.replace(/<(ul|ol)[^>]*>([\s\S]*?)<\/\1>/gi, function(
|
||||
m,
|
||||
t,
|
||||
inner
|
||||
) {
|
||||
var li = inner.split('</li>')
|
||||
li.pop()
|
||||
|
||||
for (var i = 0, len = li.length; i < len; i++) {
|
||||
var pre = t === 'ol' ? i + 1 + '. ' : '* '
|
||||
li[i] =
|
||||
pre +
|
||||
li[i]
|
||||
.replace(/\s*<li[^>]*>([\s\S]*)/i, function(m, n) {
|
||||
n = n.trim().replace(/\n/g, '\n ')
|
||||
return n
|
||||
})
|
||||
.replace(/<[\/]?[\w]*[^>]*>/g, '')
|
||||
}
|
||||
return li.join('\n')
|
||||
})
|
||||
return '\n' + match.trim()
|
||||
})
|
||||
}
|
||||
str = str
|
||||
.replace(/<[\/]?[\w]*[^>]*>/g, '')
|
||||
.replace(/```([\w\W]*)```/g, function(str, inner) {
|
||||
inner = inner
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
return '```' + inner + '```'
|
||||
})
|
||||
return str
|
||||
}
|
||||
|
||||
var defaultToolbar = [
|
||||
'h1',
|
||||
'quote',
|
||||
'|',
|
||||
'bold',
|
||||
'italic',
|
||||
'through',
|
||||
'|',
|
||||
'unordered',
|
||||
'ordered',
|
||||
'|',
|
||||
'hr',
|
||||
'link',
|
||||
'time',
|
||||
'face',
|
||||
'|',
|
||||
'table',
|
||||
'image',
|
||||
'file',
|
||||
'inlinecode',
|
||||
'blockcode',
|
||||
'|',
|
||||
'preview',
|
||||
'fullscreen',
|
||||
'|',
|
||||
'about'
|
||||
],
|
||||
extraAddons = []
|
||||
|
||||
function tool(name) {
|
||||
name = (name + '').trim().toLowerCase()
|
||||
name = '|' === name ? 'pipe' : name
|
||||
return (
|
||||
'<span title="' +
|
||||
ME.toolbar[name] +
|
||||
'" class="icon-' +
|
||||
name +
|
||||
'" ' +
|
||||
(name !== 'pipe' ? ':click="onToolClick(\'' + name + '\', $event)"' : '') +
|
||||
'></span>'
|
||||
)
|
||||
}
|
||||
|
||||
Anot.component('meditor', {
|
||||
render: function() {
|
||||
var toolbar = (this.toolbar || defaultToolbar)
|
||||
.map(function(it) {
|
||||
return tool(it)
|
||||
})
|
||||
.join('')
|
||||
delete this.toolbar
|
||||
return (
|
||||
'<div class="do-meditor do-meditor-font" :visible="editorVisible"' +
|
||||
' :class="{fullscreen: fullscreen, preview: preview}">' +
|
||||
'<div class="tool-bar do-ui-font do-fn-noselect">{toolbar}</div>' +
|
||||
'<textarea ref="textarea" class="editor-body" spellcheck="false" :duplex="plainTxt" :attr="{disabled: disabled}" :on-paste="$paste($event)"></textarea>' +
|
||||
'<content class="md-preview do-marked-theme" :visible="preview" :html="htmlTxt"></content>' +
|
||||
'</div>'
|
||||
).replace(/\{toolbar\}/g, toolbar)
|
||||
},
|
||||
|
||||
construct: function(base, opt, attr) {
|
||||
Anot.mix(base, opt, attr)
|
||||
if (base.$addons && Array.isArray(base.$addons)) {
|
||||
extraAddons = base.$addons.map(function(name) {
|
||||
return ME.path + '/addon/' + name
|
||||
})
|
||||
delete base.$addons
|
||||
}
|
||||
if (base.hasOwnProperty('$show')) {
|
||||
base.editorVisible = base.$show
|
||||
delete base.$show
|
||||
}
|
||||
return base
|
||||
},
|
||||
componentWillMount: function(vm) {},
|
||||
componentDidMount: function(vm, elem) {
|
||||
console.log(this)
|
||||
// vm.$editor = elem.children[1]
|
||||
|
||||
// editorVM.push(vm)
|
||||
// //自动加载额外的插件
|
||||
// require(extraAddons, function() {
|
||||
// var args = Array.prototype.slice.call(arguments, 0)
|
||||
// args.forEach(function(addon) {
|
||||
// addon && addon(vm)
|
||||
// })
|
||||
// })
|
||||
|
||||
// Anot(vm.$editor).bind('keydown', function(ev) {
|
||||
// var wrap = ME.selection(vm.$editor) || '',
|
||||
// select = !!wrap
|
||||
// //tab键改为插入2个空格,阻止默认事件,防止焦点失去
|
||||
// if (ev.keyCode === 9) {
|
||||
// wrap = wrap
|
||||
// .split('\n')
|
||||
// .map(function(it) {
|
||||
// return ev.shiftKey ? it.replace(/^\s\s/, '') : ' ' + it
|
||||
// })
|
||||
// .join('\n')
|
||||
// ME.insert(this, wrap, select)
|
||||
// ev.preventDefault()
|
||||
// }
|
||||
// //修复按退格键删除选中文本时,选中的状态不更新的bug
|
||||
// if (ev.keyCode === 8) {
|
||||
// if (select) {
|
||||
// ME.insert(this, '', select)
|
||||
// ev.preventDefault()
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// //编辑器成功加载的回调
|
||||
// vm.$onSuccess(ME.get(), vm)
|
||||
},
|
||||
watch: {
|
||||
plainTxt: function(val) {
|
||||
this.$compile()
|
||||
//只有开启实时预览,才会赋值给htmlTxt
|
||||
if (this.preview) {
|
||||
this.htmlTxt = this.$htmlTxt
|
||||
}
|
||||
this.$onUpdate(this.plainTxt, vm.$htmlTxt)
|
||||
}
|
||||
},
|
||||
state: {
|
||||
disabled: false, //禁用编辑器
|
||||
fullscreen: false, //是否全屏
|
||||
preview: false, //是否显示预览
|
||||
$editor: null, //编辑器元素
|
||||
editorVisible: true,
|
||||
$htmlTxt: '', //临时储存html文本
|
||||
htmlTxt: '', //用于预览渲染
|
||||
plainTxt: '', //纯md文本
|
||||
$safelyCompile: true
|
||||
},
|
||||
methods: {
|
||||
onToolClick: function(name, ev) {
|
||||
if (ME.addon[name]) {
|
||||
ME.addon[name].call(ME, ev.target, this)
|
||||
} else {
|
||||
console.log('%c没有对应的插件%c[%s]', 'color:#f00;', '', name)
|
||||
}
|
||||
},
|
||||
$onSuccess: Anot.noop,
|
||||
$onUpdate: Anot.noop,
|
||||
$onFullscreen: Anot.noop,
|
||||
$paste: function(ev) {
|
||||
ev.preventDefault()
|
||||
var txt = ev.clipboardData.getData('text/plain').trim(),
|
||||
html = ev.clipboardData.getData('text/html').trim()
|
||||
|
||||
html = html2md(html)
|
||||
|
||||
if (html) {
|
||||
ME.insert(this, html)
|
||||
} else if (txt) {
|
||||
ME.insert(this, txt)
|
||||
}
|
||||
this.plainTxt = this.value
|
||||
},
|
||||
compile: function() {
|
||||
var txt = this.plainTxt.trim()
|
||||
|
||||
if (this.$safelyCompile) {
|
||||
txt = txt
|
||||
.replace(/<script([^>]*?)>/g, '<script$1>')
|
||||
.replace(/<\/script>/g, '</script>')
|
||||
}
|
||||
//只解析,不渲染
|
||||
this.$htmlTxt = marked(txt)
|
||||
}
|
||||
}
|
||||
})
|
|
@ -1,440 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* @authors yutent (yutent@doui.cc)
|
||||
* @date 2017-04-17 16:37:12
|
||||
*
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
define([
|
||||
'yua',
|
||||
'lib/prism/base',
|
||||
'lib/marked/main',
|
||||
'css!./skin/main',
|
||||
], function(yua){
|
||||
|
||||
marked.setOptions({
|
||||
highlight: function(code, lang){
|
||||
return Prism.highlight(code, Prism.languages[lang])
|
||||
}
|
||||
})
|
||||
|
||||
var editorVM = []
|
||||
yua.ui.meditor = '1.0.0'
|
||||
//存放编辑器公共静态资源
|
||||
window.ME = {
|
||||
version: yua.ui.meditor,
|
||||
toolbar: { //工具栏title
|
||||
pipe: '',
|
||||
h1: '标题',
|
||||
quote: '引用文本',
|
||||
bold: '粗体',
|
||||
italic: '斜体',
|
||||
through: '删除线',
|
||||
unordered: '无序列表',
|
||||
ordered: '有序列表',
|
||||
link: '超链接',
|
||||
hr: '横线',
|
||||
time: '插入当前时间',
|
||||
face: '表情',
|
||||
table: '插入表格',
|
||||
image: '插入图片',
|
||||
file: '插入附件',
|
||||
inlinecode: '行内代码',
|
||||
blockcode: '代码块',
|
||||
preview: '预览',
|
||||
fullscreen: '全屏',
|
||||
about: '关于编辑器',
|
||||
},
|
||||
addon: {}, //已有插件
|
||||
//往文本框中插入内容
|
||||
insert: function(dom, val, isSelect){
|
||||
if(document.selection){
|
||||
dom.focus()
|
||||
var range = document.selection.createRange()
|
||||
range.text = val
|
||||
dom.focus()
|
||||
range.moveStart('character', -1)
|
||||
|
||||
}else if(dom.selectionStart || dom.selectionStart === 0) {
|
||||
var startPos = dom.selectionStart,
|
||||
endPos = dom.selectionEnd,
|
||||
scrollTop = dom.scrollTop;
|
||||
|
||||
dom.value = dom.value.slice(0, startPos)
|
||||
+ val
|
||||
+ dom.value.slice(endPos, dom.value.length);
|
||||
|
||||
dom.selectionStart = isSelect ? startPos : (startPos + val.length)
|
||||
dom.selectionEnd = startPos + val.length
|
||||
dom.scrollTop = scrollTop
|
||||
dom.focus()
|
||||
}else{
|
||||
dom.value += val;
|
||||
dom.focus()
|
||||
}
|
||||
},
|
||||
/**
|
||||
* [selection 获取选中的文本]
|
||||
* @param {[type]} dom [要操作的元素]
|
||||
* @param {[type]} line [是否强制选取整行]
|
||||
*/
|
||||
selection: function(dom, line){
|
||||
if(document.selection){
|
||||
return document.selection.createRange().text
|
||||
}else{
|
||||
|
||||
var startPos = dom.selectionStart,
|
||||
endPos = dom.selectionEnd;
|
||||
|
||||
if(endPos){
|
||||
//强制选择整行
|
||||
if(line) {
|
||||
startPos = dom.value.slice(0, startPos).lastIndexOf('\n');
|
||||
|
||||
var tmpEnd = dom.value.slice(endPos).indexOf('\n');
|
||||
tmpEnd = tmpEnd < 0 ? 0 : tmpEnd
|
||||
|
||||
startPos += 1 //把\n加上
|
||||
endPos += tmpEnd;
|
||||
|
||||
dom.selectionStart = startPos
|
||||
dom.selectionEnd = endPos
|
||||
}
|
||||
}else{
|
||||
//强制选择整行
|
||||
if(line) {
|
||||
endPos = dom.value.indexOf('\n')
|
||||
endPos = endPos < 0 ? dom.value.length : endPos
|
||||
dom.selectionEnd = endPos
|
||||
}
|
||||
}
|
||||
return dom.value.slice(startPos, endPos)
|
||||
}
|
||||
},
|
||||
repeat: function(str, num){
|
||||
if(String.prototype.repeat){
|
||||
return str.repeat(num)
|
||||
}else{
|
||||
var result = ''
|
||||
while(num > 0){
|
||||
result += str;
|
||||
num--
|
||||
}
|
||||
return result
|
||||
}
|
||||
},
|
||||
get: function(id){
|
||||
if(id === void 0){
|
||||
id = editorVM.length - 1
|
||||
}
|
||||
var vm = editorVM[id]
|
||||
if(vm){
|
||||
return {
|
||||
id: vm.$id,
|
||||
getVal: function(){
|
||||
return vm.plainTxt.trim()
|
||||
},
|
||||
getHtml: function(){
|
||||
return vm.$htmlTxt
|
||||
},
|
||||
setVal: function(txt){
|
||||
vm.plainTxt = txt || ''
|
||||
},
|
||||
show: function(){
|
||||
vm.editorVisible = true
|
||||
},
|
||||
hide: function(){
|
||||
vm.editorVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
},
|
||||
doc: yua(document)
|
||||
}
|
||||
//获取真实的引用路径,避免因为不同的目录结构导致加载失败的情况
|
||||
for(var i in yua.modules){
|
||||
if(/meditor/.test(i)) {
|
||||
ME.path = i.slice(0, i.lastIndexOf('/'))
|
||||
break;
|
||||
}
|
||||
}
|
||||
var elems = {
|
||||
p: function(str, attr, inner){
|
||||
return inner ? ('\n' + inner + '\n') : ''
|
||||
},
|
||||
br: '\n',
|
||||
'h([1-6])': function(str, level, attr, inner){
|
||||
var h = ME.repeat('#', level)
|
||||
return '\n' + h + ' ' + inner + '\n'
|
||||
},
|
||||
hr: '\n\n___\n\n',
|
||||
a: function(str, attr, inner){
|
||||
var href = attr.match(attrExp('href')),
|
||||
title = attr.match(attrExp('title')),
|
||||
tar = attr.match(attrExp('target'));
|
||||
|
||||
href = href && href[1] || ''
|
||||
title = title && title[1] || ''
|
||||
tar = tar && tar[1] || '_self'
|
||||
|
||||
href = href === 'javascript:void(0);' ? 'javascript:;' : href
|
||||
|
||||
return '[' + (inner || href) + '](' + href + ' "title=' + title + ';target=' + tar + '")'
|
||||
},
|
||||
em: function(str, attr, inner){
|
||||
return inner && ('_' + inner + '_') || ''
|
||||
},
|
||||
strong: function(str, attr, inner){
|
||||
return inner && ('**' + inner + '**') || ''
|
||||
},
|
||||
code: function(str, attr, inner){
|
||||
return inner && ('`' + inner + '`') || ''
|
||||
},
|
||||
pre: function(str, attr, inner){
|
||||
|
||||
return '\n\n```\n' + inner + '\n```\n'
|
||||
},
|
||||
blockquote: function(str, attr, inner){
|
||||
return '> ' + inner.trim()
|
||||
},
|
||||
img: function(str, attr, inner){
|
||||
var src = attr.match(attrExp('src')),
|
||||
alt = attr.match(attrExp('alt'));
|
||||
|
||||
src = src && src[1] || ''
|
||||
alt = alt && alt[1] || ''
|
||||
|
||||
return '![' + alt + '](' + src + ')'
|
||||
}
|
||||
}
|
||||
|
||||
function attrExp(field){
|
||||
return new RegExp(field + '\\s?=\\s?["\']?([^"\']*)["\']?', 'i')
|
||||
}
|
||||
function tagExp(tag, open){
|
||||
var exp = ''
|
||||
if(['br', 'hr', 'img'].indexOf(tag) > -1){
|
||||
exp = '<' + tag + '([^>]*)\\/?>'
|
||||
}else{
|
||||
exp = '<' + tag + '([^>]*)>([\\s\\S]*?)<\\/' + tag + '>'
|
||||
}
|
||||
return new RegExp(exp, 'gi')
|
||||
}
|
||||
function html2md(str){
|
||||
try{
|
||||
str = decodeURIComponent(str)
|
||||
}catch(err){}
|
||||
str = str.replace(/\t/g, ' ').replace(/<meta [^>]*>/, '')
|
||||
|
||||
for(var i in elems){
|
||||
var cb = elems[i],
|
||||
exp = tagExp(i);
|
||||
|
||||
if(i === 'blockquote'){
|
||||
while(str.match(exp)){
|
||||
str = str.replace(exp, cb)
|
||||
}
|
||||
}else{
|
||||
str = str.replace(exp, cb)
|
||||
}
|
||||
|
||||
if(i === 'em'){
|
||||
exp = tagExp('i')
|
||||
str = str.replace(exp, cb)
|
||||
}
|
||||
if(i === 'strong'){
|
||||
exp = tagExp('b')
|
||||
str = str.replace(exp, cb)
|
||||
}
|
||||
}
|
||||
var liExp = /<(ul|ol)[^>]*>(?:(?!<ul|<ol)[\s\S])*?<\/\1>/gi
|
||||
while(str.match(liExp)) {
|
||||
str = str.replace(liExp, function(match){
|
||||
match = match.replace(/<(ul|ol)[^>]*>([\s\S]*?)<\/\1>/gi, function(m, t, inner){
|
||||
var li = inner.split('</li>')
|
||||
li.pop()
|
||||
|
||||
for(var i = 0,len = li.length; i < len; i++){
|
||||
var pre = t === 'ol' ? ((i + 1) + '. ') : '* '
|
||||
li[i] = pre + li[i].replace(/\s*<li[^>]*>([\s\S]*)/i, function(m, n){
|
||||
n = n.trim()
|
||||
.replace(/\n/g, '\n ')
|
||||
return n
|
||||
}).replace(/<[\/]?[\w]*[^>]*>/g, '')
|
||||
}
|
||||
return li.join('\n')
|
||||
})
|
||||
return '\n' + match.trim()
|
||||
})
|
||||
}
|
||||
str = str.replace(/<[\/]?[\w]*[^>]*>/g, '')
|
||||
.replace(/```([\w\W]*)```/g, function(str, inner){
|
||||
inner = inner.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||
return '```' + inner + '```'
|
||||
})
|
||||
return str
|
||||
}
|
||||
|
||||
require([
|
||||
ME.path + '/addon/base'
|
||||
], function(){
|
||||
|
||||
|
||||
var defaultToolbar = ['h1', 'quote', '|',
|
||||
'bold', 'italic', 'through', '|',
|
||||
'unordered', 'ordered', '|',
|
||||
'hr', 'link', 'time', 'face', '|',
|
||||
'table','image', 'file','inlinecode', 'blockcode','|',
|
||||
'preview', 'fullscreen', '|',
|
||||
'about'
|
||||
],
|
||||
extraAddons = [];
|
||||
|
||||
|
||||
function tool(name){
|
||||
name = (name + '').trim().toLowerCase()
|
||||
name = '|' === name ? 'pipe' : name
|
||||
return '<span title="' + ME.toolbar[name] + '" class="icon-' + name+ '" '
|
||||
+ (name !== 'pipe' ? (':click="$onToolbarClick(\'' + name + '\')"') : '')
|
||||
+ '></span>'
|
||||
}
|
||||
|
||||
|
||||
|
||||
yua.component('meditor', {
|
||||
$template: '<div class="do-meditor do-meditor-font" :visible="editorVisible"'
|
||||
+ ' :class="{fullscreen: fullscreen, preview: preview}">'
|
||||
+ '<div class="tool-bar do-ui-font do-fn-noselect">{toolbar}</div>'
|
||||
+ '<textarea class="editor-body" spellcheck="false" :duplex="plainTxt" :attr="{disabled: disabled}" :on-paste="$paste($event)"></textarea>'
|
||||
+ '<content class="md-preview do-marked-theme" :visible="preview" :html="htmlTxt"></content>'
|
||||
+ '</div>',
|
||||
$$template: function(txt){
|
||||
|
||||
var toolbar = (this.toolbar || defaultToolbar).map(function(it){
|
||||
return tool(it)
|
||||
}).join('')
|
||||
|
||||
delete this.toolbar
|
||||
return txt.replace(/\{uuid\}/g, this.$id).replace(/\{toolbar\}/g, toolbar)
|
||||
},
|
||||
$construct: function(base, opt, attr){
|
||||
yua.mix(base, opt, attr)
|
||||
if(base.$addons && Array.isArray(base.$addons)){
|
||||
extraAddons = base.$addons.map(function(name){
|
||||
return ME.path + '/addon/' + name
|
||||
})
|
||||
delete base.$addons
|
||||
}
|
||||
if(base.hasOwnProperty('$show')){
|
||||
base.editorVisible = base.$show
|
||||
delete base.$show
|
||||
}
|
||||
return base
|
||||
},
|
||||
$init: function(vm){
|
||||
vm.$watch('plainTxt', function(val){
|
||||
vm.$compile()
|
||||
//只有开启实时预览,才会赋值给htmlTxt
|
||||
if(vm.preview){
|
||||
vm.htmlTxt = vm.$htmlTxt
|
||||
}
|
||||
vm.$onUpdate(vm.plainTxt, vm.$htmlTxt)
|
||||
})
|
||||
|
||||
vm.$onToolbarClick = function(name){
|
||||
if(ME.addon[name]){
|
||||
ME.addon[name].call(ME.addon, this, vm)
|
||||
}else{
|
||||
console.log('%c没有对应的插件%c[%s]', 'color:#f00;', '',name)
|
||||
}
|
||||
}
|
||||
|
||||
vm.$paste = function(ev){
|
||||
ev.preventDefault()
|
||||
var txt = ev.clipboardData.getData('text/plain').trim(),
|
||||
html = ev.clipboardData.getData('text/html').trim();
|
||||
|
||||
html = html2md(html)
|
||||
|
||||
if(html){
|
||||
ME.insert(this, html)
|
||||
}else if(txt) {
|
||||
ME.insert(this, txt)
|
||||
}
|
||||
vm.plainTxt = this.value
|
||||
}
|
||||
},
|
||||
$ready: function(vm, elem){
|
||||
|
||||
vm.$editor = elem.children[1]
|
||||
|
||||
editorVM.push(vm)
|
||||
//自动加载额外的插件
|
||||
require(extraAddons, function(){
|
||||
var args = Array.prototype.slice.call(arguments, 0)
|
||||
args.forEach(function(addon){
|
||||
addon && addon(vm)
|
||||
})
|
||||
})
|
||||
|
||||
yua(vm.$editor).bind('keydown', function(ev){
|
||||
|
||||
var wrap = ME.selection(vm.$editor) || '',
|
||||
select = !!wrap;
|
||||
//tab键改为插入2个空格,阻止默认事件,防止焦点失去
|
||||
if(ev.keyCode === 9){
|
||||
wrap = wrap.split('\n').map(function(it){
|
||||
return ev.shiftKey ? it.replace(/^\s\s/, '') : ' ' + it
|
||||
}).join('\n')
|
||||
ME.insert(this, wrap, select)
|
||||
ev.preventDefault()
|
||||
}
|
||||
//修复按退格键删除选中文本时,选中的状态不更新的bug
|
||||
if(ev.keyCode === 8){
|
||||
if(select){
|
||||
ME.insert(this, '', select)
|
||||
ev.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
//编辑器成功加载的回调
|
||||
vm.$onSuccess(ME.get(), vm)
|
||||
},
|
||||
$paste: yua.noop,
|
||||
$compile: function(){
|
||||
var txt = this.plainTxt.trim()
|
||||
|
||||
if(this.$safelyCompile){
|
||||
txt = txt.replace(/<script([^>]*?)>/g, '<script$1>')
|
||||
.replace(/<\/script>/g, '</script>')
|
||||
}
|
||||
//只解析,不渲染
|
||||
this.$htmlTxt = marked(txt)
|
||||
},
|
||||
$onToolbarClick: yua.noop,
|
||||
$onSuccess: yua.noop,
|
||||
$onUpdate: yua.noop,
|
||||
$onFullscreen: yua.noop,
|
||||
$safelyCompile: true,
|
||||
disabled: false, //禁用编辑器
|
||||
fullscreen: false, //是否全屏
|
||||
preview: false, //是否显示预览
|
||||
$editor: null, //编辑器元素
|
||||
editorVisible: true,
|
||||
$htmlTxt: '', //临时储存html文本
|
||||
htmlTxt: '', //用于预览渲染
|
||||
plainTxt: '' //纯md文本
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
||||
})
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
@import "../../../../css/var.scss";
|
||||
@import "var.scss";
|
||||
|
||||
.do-meditor {position:relative;width:100%;height:100%;min-height:180px;padding-top:43px;border:1px solid #ddd;background:#fff;color:#666;
|
||||
|
||||
|
@ -96,30 +96,30 @@
|
|||
.do-meditor {
|
||||
.tool-bar {overflow:hidden;position:absolute;top:0;left:0;z-index:99;width:100%;height:43px;padding:5px 10px;border-bottom:1px solid #ddd;background:#f5f5f5;color:#666;
|
||||
|
||||
span {display:inline-block;width:30px;height:32px;line-height:32px;text-align:center;font-size:20px;}
|
||||
span {display:inline-block;width:32px;height:32px;line-height:32px;text-align:center;font-size:28px;}
|
||||
span:hover {background:#e5e5e5;}
|
||||
.icon-pipe {width:20px;}
|
||||
.icon-pipe {width:20px;color:nth($cp, 3)}
|
||||
.icon-pipe:hover {background:none;}
|
||||
.icon-pipe::before {content:"\e62c"}
|
||||
.icon-h1::before {content:"\e62b"}
|
||||
.icon-bold::before {content:"\e62f"}
|
||||
.icon-italic::before {content:"\e639"}
|
||||
.icon-through::before {content:"\e619"}
|
||||
.icon-link::before {content:"\e61c"}
|
||||
.icon-inlinecode::before {content:"\e63a"}
|
||||
.icon-blockcode::before {content:"\e632"}
|
||||
.icon-quote::before {content:"\e61b"}
|
||||
.icon-hr::before {content:"\e614"}
|
||||
.icon-time::before {content:"\e636"}
|
||||
.icon-face::before {content:"\e630"}
|
||||
.icon-image::before {content:"\e637"}
|
||||
.icon-file::before {content:"\e618"}
|
||||
.icon-preview::before {content:"\e61f"}
|
||||
.icon-fullscreen::before {content:"\e621"}
|
||||
.icon-table::before {content:"\e617"}
|
||||
.icon-ordered::before {content:"\e638"}
|
||||
.icon-unordered::before {content:"\e633"}
|
||||
.icon-about::before {content:"\e700"}
|
||||
.icon-pipe::before {content:"\e677"}
|
||||
.icon-h1::before {content:"\e65c"}
|
||||
.icon-bold::before {content:"\e66c"}
|
||||
.icon-italic::before {content:"\e670"}
|
||||
.icon-through::before {content:"\e66d"}
|
||||
.icon-link::before {content:"\e667"}
|
||||
.icon-inlinecode::before {content:"\e67a"}
|
||||
.icon-blockcode::before {content:"\e67b"}
|
||||
.icon-quote::before {content:"\e66a"}
|
||||
.icon-hr::before {content:"\e676"}
|
||||
.icon-time::before {content:"\e675"}
|
||||
.icon-face::before {content:"\e673"}
|
||||
.icon-image::before {content:"\e682"}
|
||||
.icon-file::before {content:"\e66b"}
|
||||
.icon-preview::before {content:"\e67d"}
|
||||
.icon-fullscreen::before {content:"\e67e"}
|
||||
.icon-table::before {content:"\e65a"}
|
||||
.icon-ordered::before {content:"\e664"}
|
||||
.icon-unordered::before {content:"\e663"}
|
||||
.icon-about::before {content:"\e672"}
|
||||
}
|
||||
|
||||
.editor-body{overflow:hidden;overflow-y:auto;float:left;width:100%;height:100%;padding:5px 5px 50px;border:0;outline:none;resize:none;color:#666;background:#fff;}
|
||||
|
|
|
@ -22,10 +22,10 @@
|
|||
|
||||
.button,.page {display:inline-block;border:0;color: nth($cgr, 1);text-decoration:none;cursor:pointer;vertical-align:top;font-size:14px;font-weight:100;
|
||||
|
||||
&.home::after {content:"\e652";font-size:18px;}
|
||||
&.prev::after {content:"\e659";font-size:18px;}
|
||||
&.next::after {content:"\e658";font-size:18px;}
|
||||
&.end::after {content:"\e653";font-size:18px;}
|
||||
&.home::after {content:"\e691";font-size:18px;}
|
||||
&.prev::after {content:"\e67c";font-size:18px;}
|
||||
&.next::after {content:"\e66e";font-size:18px;}
|
||||
&.end::after {content:"\e693";font-size:18px;}
|
||||
}
|
||||
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
1889
src/js/prism/full.js
1889
src/js/prism/full.js
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue