This repository has been archived on 2023-08-30. You can view files and clone it, but cannot push or open issues/pull-requests.
bytedo
/
wcui
Archived
1
0
Fork 0

重绘一大波icon;修复框架子vm的props属性传递;重写datepicker组件;重写分页组件;

old
宇天 2018-02-03 02:10:34 +08:00
parent c76a1b3264
commit 88dab988da
25 changed files with 5987 additions and 6868 deletions

View File

@ -19,7 +19,12 @@ const prefixer = postcss().use(
) )
const jsOpt = { const jsOpt = {
presets: ['es2015'], presets: ['es2015'],
plugins: ['transform-es2015-modules-amd'] plugins: [
'transform-es2015-modules-amd',
'transform-decorators-legacy',
'transform-class-properties',
'transform-object-rest-spread'
]
} }
const cssOpt = { const cssOpt = {
includePaths: ['src/css/'], includePaths: ['src/css/'],

View File

@ -18,7 +18,12 @@ const prefixer = postcss().use(
) )
const jsOpt = { const jsOpt = {
presets: ['es2015', 'minify'], 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 = { const cssOpt = {
includePaths: ['src/css/'], includePaths: ['src/css/'],

53
package-lock.json generated
View File

@ -1,5 +1,5 @@
{ {
"name": "doui-yua", "name": "doui-anot",
"version": "0.0.1", "version": "0.0.1",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
@ -463,6 +463,47 @@
"babel-helper-is-void-0": "0.2.0" "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": { "babel-plugin-transform-es2015-arrow-functions": {
"version": "6.22.0", "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", "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==", "integrity": "sha512-bPbUhkeN2Nc0KH0/A19GwQGj8w+CvdJzyu8t59VoEDgsNMQ9Bopzi5DrVkrSsVjbYUaZpzq/DYLrH+wD5K2Tig==",
"dev": true "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": { "babel-plugin-transform-property-literals": {
"version": "6.8.5", "version": "6.8.5",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.8.5.tgz", "resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.8.5.tgz",

View File

@ -1,5 +1,5 @@
{ {
"name": "doui-yua", "name": "doui-anot",
"version": "0.0.1", "version": "0.0.1",
"description": "基于Anot框架的doUI组件库。支持IE10+,及现代浏览器。", "description": "基于Anot框架的doUI组件库。支持IE10+,及现代浏览器。",
"main": "index.js", "main": "index.js",
@ -13,13 +13,16 @@
}, },
"keywords": [ "keywords": [
"doui", "doui",
"yua" "Anot"
], ],
"author": "yutent", "author": "yutent",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"autoprefixer": "^7.2.5", "autoprefixer": "^7.2.5",
"babel-core": "^6.26.0", "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-es2015": "^6.24.1",
"babel-preset-minify": "^0.2.0", "babel-preset-minify": "^0.2.0",
"chalk": "^2.3.0", "chalk": "^2.3.0",

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -3297,11 +3297,12 @@
if (/^:/.test(attr.name)) { if (/^:/.test(attr.name)) {
var name = attr.name.match(rmsAttr)[1] var name = attr.name.match(rmsAttr)[1]
var value = null var value = null
if (!name || Anot.directives[name]) { if (!name || Anot.directives[name] || events[name]) {
return return
} }
try { try {
value = parseExpr(attr.value, vmodels, {}).apply(0, vmodels) value = parseExpr(attr.value, vmodels, {}).apply(0, vmodels)
value = toJson(value)
elem.removeAttribute(attr.name) elem.removeAttribute(attr.name)
if (!value) { if (!value) {
return return
@ -4092,7 +4093,7 @@
elem.addEventListener(type, callback, false) elem.addEventListener(type, callback, false)
var old = binding.rollback var old = binding.rollback
binding.rollback = function() { binding.rollback = function() {
elem.anotStter = null elem.anotSetter = null
Anot.unbind(elem, type, callback) Anot.unbind(elem, type, callback)
old && old() old && old()
} }
@ -4196,7 +4197,7 @@
elem.msFocus = false elem.msFocus = false
}) })
} }
elem.anotStter = updateVModel //#765 elem.anotSetter = updateVModel //#765
watchValueInTimer(function() { watchValueInTimer(function() {
if (root.contains(elem)) { if (root.contains(elem)) {
if (!elem.msFocus) { if (!elem.msFocus) {
@ -4346,8 +4347,8 @@
function newSetter(value) { function newSetter(value) {
// jshint ignore:line // jshint ignore:line
setters[this.tagName].call(this, value) setters[this.tagName].call(this, value)
if (!this.msFocus && this.anotStter) { if (!this.msFocus && this.anotSetter) {
this.anotStter() this.anotSetter()
} }
} }
var inputProto = HTMLInputElement.prototype var inputProto = HTMLInputElement.prototype

View File

@ -42,16 +42,16 @@
&:active {font-weight:bold; &:active {font-weight:bold;
&::before {animation:ripple .3s cubic-bezier(0.23, 1, 0.32, 1);} &::before {animation:ripple .3s cubic-bezier(0.23, 1, 0.32, 1);}
} }
&::after {content:"\e652";} &::after {content:"\e692";}
&.prev-month {left:35px; &.prev-month {left:35px;
&::after {content:"\e659"} &::after {content:"\e67c"}
} }
&.next-month {left:auto; right:35px; &.next-month {left:auto; right:35px;
&::after {content:"\e658"} &::after {content:"\e66e"}
} }
&.next-year {left:auto; right:0; &.next-year {left:auto; right:0;
&::after {content:"\e653"} &::after {content:"\e694"}
} }
} }

219
src/js/drag/index.js Normal file
View File

@ -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)
}
})
})
}
})

View File

@ -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)
}
});
})
}
})
})

View File

@ -5,27 +5,23 @@
* *
*/ */
"use strict"; 'use strict'
import 'drag/index'
import './skin/def.scss'
define(['yua', 'lib/drag/main', 'css!./skin/def'], function(yua){ Anot.ui.layer = '1.0.0-base'
let layerDom = {}
if(window.layer){ let layerObj = {}
return window.layer let unique = null //储存当前打开的1/2/3类型的弹窗
} let lid = 0
let defconf = {
yua.ui.layer = '1.0.0-base'
var layerDom = {},
layerObj = {},
unique = null, //储存当前打开的1/2/3类型的弹窗
lid = 0,
defconf = {
type: 1, // 弹窗类型 type: 1, // 弹窗类型
skin: 'def', //默认主题 skin: 'def', //默认主题
icon: 1, //图标类型 icon: 1, //图标类型
background: '#fff', background: '#fff',
shade: true, //遮罩 mask: true, //遮罩
shadeClose: false, //遮罩点击关闭弹窗 maskClose: false, //遮罩点击关闭弹窗
radius: '0px', //弹窗圆角半径 radius: '0px', //弹窗圆角半径
area: ['auto', 'auto'], area: ['auto', 'auto'],
title: '提示', //弹窗主标题(在工具栏上的) title: '提示', //弹窗主标题(在工具栏上的)
@ -33,43 +29,39 @@ define(['yua', 'lib/drag/main', 'css!./skin/def'], function(yua){
content: '', // 弹窗的内容 content: '', // 弹窗的内容
fixed: false, //是否固定不可拖拽 fixed: false, //是否固定不可拖拽
offset: null, //弹窗出来时的坐标, 为数组,可有4个值,依次是 上右下左 offset: null, //弹窗出来时的坐标, 为数组,可有4个值,依次是 上右下左
btns: ['确定', '取消'], //弹窗的2个按钮的文字 btns: ['确定', '取消'] //弹窗的2个按钮的文字
yes: yua.noop, //确定按钮对应的回调 }
no: yua.noop, //取消按钮对应的回调 const uuid = function() {
success: null //弹窗初始化完成时的回调 return 'layer-' + ++lid
}, }
uuid = function(){ const close = function(id) {
return 'layer-' + (++lid)
},
close = function(id){
if (typeof id !== 'string' && typeof id !== 'number') { if (typeof id !== 'string' && typeof id !== 'number') {
return yua.error('要关闭的layer实例不存在') return Anot.error('要关闭的layer实例不存在')
} }
if (/^\$wrap\-/.test(id) || layerObj['$wrap-' + id]) { if (/^\$wrap\-/.test(id) || layerObj['$wrap-' + id]) {
try { try {
id = (layerObj['$wrap-' + id] ? '$wrap-' : '') + id; id = (layerObj['$wrap-' + id] ? '$wrap-' : '') + id
//未显示过,忽略 //未显示过,忽略
if (!layerObj[id].show) { if (!layerObj[id].show) {
return return
} }
layerObj[id].parentElem.replaceChild(layerObj[id].wrap, layerDom[id][1]) layerObj[id].parentElem.replaceChild(layerObj[id].wrap, layerDom[id][0])
layerObj[id].wrap.style.display = 'none' layerObj[id].wrap.style.display = 'none'
layerObj[id].show = false layerObj[id].show = false
} catch (err) {} } catch (err) {}
} else { } else {
try { try {
document.body.removeChild(layerDom[id][1]) // document.body.removeChild(layerDom[id][1])
document.body.removeChild(layerDom[id][0]) document.body.removeChild(layerDom[id][0])
unique = null unique = null
} catch (err) {} } catch (err) {}
delete layerDom[id] delete layerDom[id]
delete yua.vmodels[id] delete Anot.vmodels[id]
} }
}, }
reapeat = function(str, num){
const reapeat = function(str, num) {
var idx = 0, var idx = 0,
result = '' result = ''
while (idx < num) { while (idx < num) {
@ -77,23 +69,34 @@ define(['yua', 'lib/drag/main', 'css!./skin/def'], function(yua){
idx++ idx++
} }
return result return result
}, }
fixOffset = function (val){ const fixOffset = function(val) {
if (!val && val !== 0) { if (!val && val !== 0) {
return 'auto' return 'auto'
} else { } else {
return val return val
} }
},
__constructor = function(conf){
if(conf){
this.ready(conf).append().show()
} }
}, const __layer__ = function(conf) {
__layer = { if (conf) {
let { yes, no, success } = conf
delete conf.yes
delete conf.no
delete conf.success
this.construct({
state: { ...conf },
props: { yes, no, success }
})
.append()
.show()
}
}
const _layer = {
alert: function(msg, conf) { alert: function(msg, conf) {
if (typeof conf === 'function') { if (typeof conf === 'function') {
conf = {yes: conf, no: conf} conf = { methods: { yes: conf, no: conf } }
} else if (typeof conf === 'object') { } else if (typeof conf === 'object') {
conf = conf conf = conf
} else { } else {
@ -101,7 +104,8 @@ define(['yua', 'lib/drag/main', 'css!./skin/def'], function(yua){
} }
conf.icon = 5 conf.icon = 5
conf.content = msg conf.content = msg
return __layer.open(conf) conf.fixed = true
return _layer.open(conf)
}, },
confirm: function(msg, yescb, nocb) { confirm: function(msg, yescb, nocb) {
var conf = {} var conf = {}
@ -116,7 +120,8 @@ define(['yua', 'lib/drag/main', 'css!./skin/def'], function(yua){
if (typeof nocb === 'function') { if (typeof nocb === 'function') {
conf.no = nocb conf.no = nocb
} }
return __layer.open(conf) conf.fixed = true
return _layer.open(conf)
}, },
msg: function(msg, conf) { msg: function(msg, conf) {
if (typeof conf !== 'object') { if (typeof conf !== 'object') {
@ -131,32 +136,40 @@ define(['yua', 'lib/drag/main', 'css!./skin/def'], function(yua){
conf.timeout = 2500 conf.timeout = 2500
} }
conf.specialMode = true;//特殊模式 conf.specialMode = true //特殊模式
conf.content = '<p class="msg-box">' + msg + '</p>' conf.content = '<p class="msg-box">' + msg + '</p>'
conf.type = 7 conf.type = 7
conf.fixed = true conf.fixed = true
conf.shade = false conf.shade = false
conf.menubar = false conf.menubar = false
conf.radius = '5px' conf.radius = '5px'
return __layer.open(conf) return _layer.open(conf)
}, },
loading: function(style, time, cb) { loading: function(style, time, cb) {
style = style >>> 0 style = style >>> 0
if (typeof time === 'function') { if (typeof time === 'function') {
cb = time; cb = time
time = 0 time = 0
} else { } else {
time = time >>> 0 time = time >>> 0
if (typeof cb !== 'function') { if (typeof cb !== 'function') {
cb = yua.noop cb = Anot.noop
} }
} }
return __layer.open({type: 6, load: style, yes: cb, timeout: time, menubar: false, background: 'none', fixed: true}) return _layer.open({
type: 6,
load: style,
yes: cb,
timeout: time,
menubar: false,
background: 'none',
fixed: true
})
}, },
tips: function(msg, elem, conf) { tips: function(msg, elem, conf) {
if (!(elem instanceof HTMLElement)) { if (!(elem instanceof HTMLElement)) {
return yua.error('tips类型必须指定一个目标容器') return Anot.error('tips类型必须指定一个目标容器')
} }
if (typeof conf !== 'object') { if (typeof conf !== 'object') {
var tmp = conf var tmp = conf
@ -176,30 +189,31 @@ define(['yua', 'lib/drag/main', 'css!./skin/def'], function(yua){
} }
conf.$elem = elem conf.$elem = elem
conf.content = msg conf.content = msg
conf.type = 5; conf.type = 5
conf.icon = 0; conf.icon = 0
conf.fixed = true; conf.fixed = true
conf.shade = false; conf.shade = false
conf.menubar = false; conf.menubar = false
return __layer.open(conf) return _layer.open(conf)
}, },
prompt: function(msg, yescb) { prompt: function(msg, yescb) {
if (typeof yescb !== 'function') { if (typeof yescb !== 'function') {
return console.error('argument [callback] requires a function, but ' + (typeof yescb) + ' given') return console.error(
'argument [callback] requires a function, but ' +
typeof yescb +
' given'
)
} }
var conf = { var conf = {
type: 3, type: 3,
prompt: '', prompt: '',
title: msg, title: msg,
content: '<input class="prompt-value" :class="{alert: !prompt}" :duplex="prompt" />', content:
yes: function(id){ '<input class="prompt-value" data-duplex-focus :class="{alert: !prompt}" :duplex="prompt" />',
if(!yua.vmodels[id].prompt){ fixed: true,
return yes: yescb
} }
yescb(id, yua.vmodels[id].prompt) return _layer.open(conf)
}
}
return __layer.open(conf)
}, },
use: function(skin, callback) { use: function(skin, callback) {
require(['css!./skin/' + skin], callback) require(['css!./skin/' + skin], callback)
@ -207,7 +221,7 @@ define(['yua', 'lib/drag/main', 'css!./skin/def'], function(yua){
close: close, close: close,
open: function(conf) { open: function(conf) {
if (typeof conf === 'string') { if (typeof conf === 'string') {
conf = '$wrap-' + conf /*conf = '$wrap-' + conf
if (!layerObj[conf]) { if (!layerObj[conf]) {
throw new Error('layer实例不存在') throw new Error('layer实例不存在')
} else { } else {
@ -217,26 +231,26 @@ define(['yua', 'lib/drag/main', 'css!./skin/def'], function(yua){
} }
layerObj[conf].show = true layerObj[conf].show = true
if(!yua.vmodels[conf]){ if (!Anot.vmodels[conf]) {
yua(layerObj[conf].obj.init) Anot(layerObj[conf].obj.init)
} }
layerObj[conf].parentElem.appendChild(layerDom[conf][1]) layerObj[conf].parentElem.appendChild(layerDom[conf][1])
layerDom[conf][1].querySelector('.detail').appendChild(layerObj[conf].wrap) layerDom[conf][1]
.querySelector('.detail')
.appendChild(layerObj[conf].wrap)
layerObj[conf].wrap.style.display = '' layerObj[conf].wrap.style.display = ''
yua.scan(layerDom[conf][1]) // Anot.scan(layerDom[conf][1])
layerObj[conf].obj.show() layerObj[conf].obj.show()
return conf return conf
} }*/
} else { } else {
return new __constructor(conf).init.$id return new __layer__(conf).init.$id
} }
}, },
version: yua.ui.layer version: Anot.ui.layer
}; }
defconf.yes = defconf.no = close
/*type: { // 弹窗类型对应的id值 /*type: { // 弹窗类型对应的id值
1: 'alert', 1: 'alert',
2: 'confirm', 2: 'confirm',
@ -246,8 +260,9 @@ define(['yua', 'lib/drag/main', 'css!./skin/def'], function(yua){
6: 'loading', 6: 'loading',
7: 'msg', 7: 'msg',
}*/ }*/
__constructor.prototype = { __layer__.prototype = {
dot: { //loading的子元素数量 dot: {
//loading的子元素数量
1: 0, 1: 0,
2: 0, 2: 0,
3: 5, 3: 5,
@ -255,252 +270,308 @@ define(['yua', 'lib/drag/main', 'css!./skin/def'], function(yua){
5: 9 5: 9
}, },
timeout: null, timeout: null,
create: function(){ construct: function(conf) {
var layBox = document.createElement('div'), let _id = conf.$id || uuid()
coverBox = document.createElement('div'); this.init = {
$id: _id,
coverBox.className = 'do-layer-cover type-' + this.init.type state: {
// 允许点击遮罩关闭弹层时, 添加控制器 ...defconf,
if(this.init.shadeClose){ ...conf.state
coverBox.setAttribute(':controller', this.cInit.$id) },
coverBox.setAttribute(':click', 'close(\'' + this.init.$id + '\')') props: conf.props,
methods: {
onMaskClick: function() {
if (this.type < 4) {
this.$refs.layer.classList.add('scale')
setTimeout(() => {
this.$refs.layer.classList.remove('scale')
}, 100)
}
},
handleConfirm: function() {
if (this.type === 3) {
if (!this.prompt) {
return
}
}
if (typeof this.props.yes === 'function') {
this.props.yes.call(this, this.prompt, this.$id)
} else {
this.close()
}
},
handleCancel: function() {
if (typeof this.props.no === 'function') {
this.props.no.call(this, this.$id)
} else {
this.close()
}
},
close: function() {
close(this.$id)
},
cancelBubble: function(ev) {
ev.cancelBubble = true
}
},
mounted: function() {
if (typeof this.success === 'function') {
this.success(_id)
}
}
} }
layBox.className = 'do-layer skin-' if (this.init.state.icon > 9) {
+ this.init.skin this.init.state.icon = 9
+ (this.init.type === 5 && ' active' || '') }
+ ' type-' //base版没有iframe类型
+ ((!this.init.specialMode && this.init.type === 7) ? 'unspecial' : this.init.type); if (this.init.state.type === 4) {
this.icon.state.type = 7
}
console.log(this.init)
return this
},
create: function() {
let { state, $id } = this.init
let outerBox = document.createElement('div')
let layBox = document.createElement('div')
outerBox.setAttribute('anot', $id)
outerBox.setAttribute(':click', 'onMaskClick')
outerBox.classList.add('do-layer')
if (state.mask) {
outerBox.classList.add('mask')
}
layBox.classList.add('layer-box')
layBox.classList.add('skin-' + state.skin)
if (state.type === 5) {
layBox.classList.add('active')
}
if (state.specialMode && state.type === 7) {
layBox.classList.add('type-unspecial')
} else {
layBox.classList.add('type-' + state.type)
}
layBox.setAttribute('ref', 'layer')
layBox.setAttribute(':click', 'cancelBubble')
//暂时隐藏,避免修正定位时,能看到闪一下 //暂时隐藏,避免修正定位时,能看到闪一下
layBox.style.visibility = 'hidden' layBox.style.cssText =
layBox.style.borderRadius = this.init.radius 'visibility:hidden; border-radius:' + state.radius + 'px'
layBox.setAttribute(':controller', this.init.$id)
//没有菜单栏, 且未禁止拖拽,则加上可拖拽属性 //没有菜单栏, 且未禁止拖拽,则加上可拖拽属性
if(!this.init.menubar && !this.init.fixed){ if (!state.menubar && !state.fixed) {
layBox.setAttribute(':drag', '') layBox.setAttribute(':drag', '')
layBox.setAttribute('data-limit', 'window') layBox.setAttribute('data-limit', 'window')
} }
//弹窗的宽高 //弹窗的宽高
var boxcss = '' var boxcss = ''
if(this.init.area[0] !== 'auto'){ if (state.area[0] !== 'auto') {
boxcss += 'width: ' + this.init.area[0] + ';' boxcss += 'width: ' + state.area[0] + ';'
} }
if(this.init.area[1] !== 'auto'){ if (state.area[1] !== 'auto') {
boxcss += 'height: ' + this.init.area[1] + ';' boxcss += 'height: ' + state.area[1] + ';'
}
let arrow = ''
if (state.type === 5) {
arrow += `<i class="arrow" style="border-top-color: ${
state.background
};"></i>`
} }
layBox.innerHTML = this.getMenubar() layBox.innerHTML = `
+ '<div class="layer-content do-layer-cl ' ${this.getMenubar()}
+ (this.init.icon < 0 && 'none-icon' || '') <div
+ '" style="' class="layer-content do-fn-cl ${state.icon < 0 ? 'none-icon' : ''}"
+ boxcss style="${boxcss}">
+ '">'
+ this.getCont() ${this.getCont()}
+ '</div>' </div>
+ this.getBtns() ${this.getCtrl()}
+ (this.init.type === 5 && '<i class="arrow" style="border-top-color: ' ${arrow}
+ this.init.background `
+ '"></i>' || '') delete state.wrap
delete this.init.wrap outerBox.appendChild(layBox)
return [this.init.shade ? coverBox : null, layBox] return [outerBox, layBox]
}, },
getCont: function() { getCont: function() {
if(this.init.type === 6){ let { state, $id } = this.init
return this.getLoading(this.init.load) if (state.type === 6) {
return this.getLoading(state.load)
} else { } else {
return this.getIcon() return `
+ '<div class="detail" ' ${this.getIcon()}
+ (this.init.wrap ? '' : ':html="content"') <div class="detail" ${!state.wrap ? ':html="content"' : ''}></div>
+ '></div>' `
} }
}, },
getLoading: function(style) { getLoading: function(style) {
return '<div class="loading-box style-' return `
+ style <div class="loading style-${style}">
+ '">' <span class="dot-box">
+ '<span class="dot-box">' ${repeat('<i></i>', this.dot[style])}
+ reapeat('<i></i>', this.dot[style]) </span>
+ '</span>' </div>
+ '</div>' `
}, },
//获取窗口导航条 //获取窗口导航条
getMenubar: function() { getMenubar: function() {
var html = '' let { state, $id } = this.init
if(this.init.menubar){ let html = ''
html += '<div class="layer-title do-fn-noselect" '; if (state.menubar) {
//可拖拽 html = `
if(!this.init.fixed){ <div class="layer-title do-fn-noselect"
html += ':drag="do-layer" data-limit="window" ' :text="title"
} ${!state.fixed ? ':drag="layer-box" data-limit="window"' : ''}>
</div>
html += '>{{title}}' `
+ '<a class="action-close do-ui-font" :click="no(\'' + this.init.$id + '\')"></a>'
+ '</div>'
} }
return html return html
}, },
//获取窗口内容的图标 //获取窗口内容的图标
getIcon: function() { getIcon: function() {
if(this.init.icon < 0){ let { state, $id } = this.init
return '' if (state.type < 4 || state.type === 5 || state.specialMode) {
} return `<span class="do-ui-font msg-icon icon-${state.icon}"></span>`
if(this.init.type < 4 || this.init.type === 5 || this.init.specialMode){
return '<span class="do-ui-font msg-icon icon-' + this.init.icon + '"></span>'
} }
return '' return ''
}, },
// 获取窗口按钮 // 获取窗口按钮
getBtns: function(){ getCtrl: function() {
if(this.init.type > 3){ let { state, $id } = this.init
if (state.type > 3) {
return '' return ''
} else { } else {
var html = '<div class="layer-btns do-fn-noselect">'; let html = ''
if(this.init.type > 1){ let btns = `
html += '<a href="javascript:;" class="action-no" ' <a href="javascript:;" class="action-yes"
+ ':click="no(\'' + this.init.$id + '\')" ' :click="handleConfirm"
+ ':text="btns[1]"></a>' tabindex="-1"
+ '<a href="javascript:;" class="action-yes" ' :text="btns[0]"
+ ':click="yes(\'' + this.init.$id + '\')" ' ></a>
+ ':text="btns[0]"></a>' `
}else{ if (state.type > 1) {
html += '<a href="javascript:;" class="action-yes" ' btns =
+ ':click="yes(\'' + this.init.$id + '\')" ' `
+ ':text="btns[0]"></a>' <a href="javascript:;" class="action-no"
:click="handleCancel"
:text="btns[1]"
></a>
` + btns
} }
html += '</div>' html = `
<div class="layer-ctrl do-fn-noselect">
${btns}
</div>
`
return html return html
} }
}, },
append: function() { append: function() {
let { state, $id } = this.init
//如果有已经打开的弹窗,则关闭 //如果有已经打开的弹窗,则关闭
if (unique) { if (unique) {
__layer.close(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(this.cInit)
yua.scan(layerDom[this.init.$id][0])
} }
if (state.type < 4) {
unique = $id
} }
layerDom[$id] = this.create()
document.body.appendChild(layerDom[this.init.$id][1]) delete state.specialMode
yua(this.init) // if (layerDom[this.init.$id][0]) {
yua.scan(layerDom[this.init.$id][1]) // document.body.appendChild(layerDom[this.init.$id][0])
// //仅在允许点击遮罩时,初始化控制器,减少资源消耗
// if (this.init.shadeClose) {
// Anot(this.cInit)
// // Anot.scan(layerDom[this.init.$id][0])
// }
// }
document.body.appendChild(layerDom[$id][0])
this.vm = Anot(this.init)
// Anot.scan(layerDom[this.init.$id][1])
return this return this
}, },
show: function() { show: function() {
var _this = this; let { state, $id } = this.init
var _this = this
setTimeout(function() { setTimeout(function() {
var style = {visibility: '', background: _this.init.background}, var style = { visibility: '', background: state.background }
css = getComputedStyle(layerDom[_this.init.$id][1]); let css = getComputedStyle(layerDom[$id][1])
if(_this.init.type === 5){ if (state.type === 5) {
style.color = _this.init.color style.color = state.color
var $elem = yua(_this.init.$elem), let $elem = Anot(_this.init.$elem)
ew = $elem.innerWidth(), let ew = $elem.innerWidth()
ol = $elem.offset().left - document.body.scrollLeft, let ol = $elem.offset().left - document.body.scrollLeft
ot = $elem.offset().top - document.body.scrollTop; let ot = $elem.offset().top - document.body.scrollTop
style.left = ol + (ew * 0.7) style.left = ol + ew * 0.7
style.top = ot - parseInt(css.height) - 8 style.top = ot - parseInt(css.height) - 8
} else { } else {
if(_this.init.offset){ if (state.offset) {
style.top = fixOffset(_this.init.offset[0]) style.top = fixOffset(state.offset[0])
style.right = fixOffset(_this.init.offset[1]) style.right = fixOffset(state.offset[1])
style.bottom = fixOffset(_this.init.offset[2]) style.bottom = fixOffset(state.offset[2])
style.left = fixOffset(_this.init.offset[3]) style.left = fixOffset(state.offset[3])
//左右都为auto时,改为居中 //左右都为auto时,改为居中
if (style.left === 'auto' && style.right === 'auto') { if (style.left === 'auto' && style.right === 'auto') {
style.left = '50%' style.left = '50%'
style.marginLeft = -parseInt(css.width) / 2; style.marginLeft = -parseInt(css.width) / 2
} }
//上下都为auto时,同样改为居中 //上下都为auto时,同样改为居中
if (style.top === 'auto' && style.bottom === 'auto') { if (style.top === 'auto' && style.bottom === 'auto') {
style.top = '50%' style.top = '50%'
style.marginTop = -parseInt(css.height) / 2; style.marginTop = -parseInt(css.height) / 2
} }
} else { } else {
style = yua.mix(style, { style = Anot.mix(style, {
marginLeft: -parseInt(css.width) / 2, marginLeft: -parseInt(css.width) / 2,
marginTop: -parseInt(css.height) / 2, marginTop: -parseInt(css.height) / 2
}) })
} }
} }
yua(layerDom[_this.init.$id][1]).css(style) Anot(layerDom[_this.init.$id][1]).css(style)
}, 4) }, 4)
// if (this.init.success && typeof this.init.success === 'function') {
if(this.init.success && typeof this.init.success === 'function'){ // //弹窗成功的回调
//弹窗成功的回调 // this.init.success(this.init.$id)
this.init.success(this.init.$id) // }
}
// loading类型,回调需要自动触发 // loading类型,回调需要自动触发
if(this.init.type > 3) { if (state.type > 3) {
//大于0自动触发超时关闭 //大于0自动触发超时关闭
if(this.init.timeout > 0){ if (state.timeout > 0) {
clearTimeout(this.timeout) clearTimeout(this.timeout)
this.timeout = setTimeout(function() { this.timeout = setTimeout(function() {
clearTimeout(_this.timeout) clearTimeout(_this.timeout)
__layer.close(_this.init.$id) _layer.close($id)
// 为loading类型时,自动关闭同时触发回调 // 为loading类型时,自动关闭同时触发回调
if(_this.init.type === 6){ if (state.type === 6) {
_this.init.yes(_this.init.$id) _this.vm.yes($id)
} }
}, state.timeout)
}, this.init.timeout) } else if (statetype === 6) {
} else if(this.init.type === 6) {
// loading类型, 非自动关闭时, 主动触发回调 // loading类型, 非自动关闭时, 主动触发回调
this.init.yes(this.init.$id) this.vm.yes($id)
} }
} }
},
ready: function(conf){
this.init = yua.mix({}, defconf, conf)
if(!this.init.$id){
this.init.$id = uuid();
}
if(this.init.icon > 17){
this.init.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
} }
} }
Anot.directive('layer', {
yua.directive('layer', {
priority: 1400, priority: 1400,
init: function(binding) { init: function(binding) {
if (!binding.param || binding.param !== 'tips') { if (!binding.param || binding.param !== 'tips') {
binding.param = '' //去掉param,保证之后的逻辑处理正常 binding.param = '' //去掉param,保证之后的逻辑处理正常
// 去掉:layer属性,避免二次扫描 // 去掉:layer属性,避免二次扫描
binding.element.removeAttribute(binding.name) binding.element.removeAttribute(binding.name)
@ -509,11 +580,17 @@ define(['yua', 'lib/drag/main', 'css!./skin/def'], function(yua){
}, },
update: function(val) { update: function(val) {
if (!val) { if (!val) {
return yua.error(':layer指令格式不正确或无效属性. [' + this.name + '="' + this.expr + '"]') return Anot.error(
':layer指令格式不正确或无效属性. [' +
this.name +
'="' +
this.expr +
'"]'
)
} }
var _this = this, var _this = this,
init = Object.assign({}, this.element.dataset); init = Object.assign({}, this.element.dataset)
if (init.hasOwnProperty('area')) { if (init.hasOwnProperty('area')) {
init.area = init.area.split(',') init.area = init.area.split(',')
@ -527,33 +604,37 @@ define(['yua', 'lib/drag/main', 'css!./skin/def'], function(yua){
if (!this.param) { if (!this.param) {
init.wrap = true init.wrap = true
init.type = 7; init.type = 7
init.$id = '$wrap-' + val; init.$id = '$wrap-' + val
if (!init.hasOwnProperty('menubar')) { if (!init.hasOwnProperty('menubar')) {
init.menubar = false; init.menubar = false
} }
var tmp = new __constructor().ready(init); var tmp = new __layer__().construct(init)
//去掉data-*属性 //去掉data-*属性
for (var i in this.element.dataset) { for (var i in this.element.dataset) {
delete this.element.dataset[i] delete this.element.dataset[i]
} }
layerObj[tmp.init.$id] = {obj: tmp, parentElem: this.element.parentNode, wrap: this.element, show: false}; layerObj[tmp.init.$id] = {
layerDom[tmp.init.$id] = tmp.create(); obj: tmp,
parentElem: this.element.parentNode,
wrap: this.element,
show: false
}
layerDom[tmp.init.$id] = tmp.create()
} else if (this.param === 'tips') { } else if (this.param === 'tips') {
var $elem = yua(this.element), var $elem = Anot(this.element),
ew = $elem.innerWidth(), ew = $elem.innerWidth(),
ol = $elem.offset().left - document.body.scrollLeft, ol = $elem.offset().left - document.body.scrollLeft,
ot = $elem.offset().top - document.body.scrollTop, ot = $elem.offset().top - document.body.scrollTop,
tipsBox = document.createElement('div'), tipsBox = document.createElement('div'),
tipsArrow = document.createElement('i'), tipsArrow = document.createElement('i'),
tipsCont = document.createElement('div'); tipsCont = document.createElement('div')
tipsBox.className = 'do-layer skin-' + (init.skin || 'def') + ' type-5' tipsBox.className = 'do-layer skin-' + (init.skin || 'def') + ' type-5'
tipsBox.style.left = ol + (ew * 0.7) + 'px' tipsBox.style.left = ol + ew * 0.7 + 'px'
if (init.background) { if (init.background) {
tipsBox.style.background = init.background tipsBox.style.background = init.background
tipsArrow.style.borderTopColor = init.background tipsArrow.style.borderTopColor = init.background
@ -567,14 +648,12 @@ define(['yua', 'lib/drag/main', 'css!./skin/def'], function(yua){
tipsBox.appendChild(tipsCont) tipsBox.appendChild(tipsCont)
tipsBox.appendChild(tipsArrow) tipsBox.appendChild(tipsArrow)
Anot(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'
yua(document).bind('scroll', function(){ tipsBox.style.top = ot - tipsBox.offsetHeight - 8 + 'px'
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) { $elem.bind('mouseenter', function(ev) {
@ -582,11 +661,9 @@ define(['yua', 'lib/drag/main', 'css!./skin/def'], function(yua){
clearTimeout(_this.showTime) clearTimeout(_this.showTime)
clearTimeout(_this.hideTime) clearTimeout(_this.hideTime)
_this.showTime = setTimeout(function() { _this.showTime = setTimeout(function() {
tipsBox.style.top = (ot - tipsBox.offsetHeight - 8) + 'px' tipsBox.style.top = ot - tipsBox.offsetHeight - 8 + 'px'
tipsBox.classList.add('active') tipsBox.classList.add('active')
}, 4) }, 4)
}) })
$elem.bind('mouseleave', function() { $elem.bind('mouseleave', function() {
_this.hideTime = setTimeout(function() { _this.hideTime = setTimeout(function() {
@ -600,10 +677,6 @@ define(['yua', 'lib/drag/main', 'css!./skin/def'], function(yua){
} }
}) })
window.layer = _layer
export default _layer
window.layer = __layer
return __layer
})

View File

@ -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
})

View File

@ -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
})

View File

@ -6,22 +6,28 @@
* @version $Id$ * @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;} a {text-decoration:none;}
/* 默认皮肤 */ .layer-box {position:absolute;left:50%;top:50%;z-index:65535;
&.skin-def {color:#666;font-size:14px;box-shadow:0 0 10px rgba(0,0,0,.3);
.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-1::before {content:"\e610";color:nth($ct, 1);} // get
.icon-2::before {content:"\e6f8";color:nth($cb, 1);} // happy .icon-2::before {content:"\e6f8";color:nth($cb, 1);} // happy
.icon-3::before {content:"\e6fd";color:nth($co, 1);} // sad .icon-3::before {content:"\e6fd";color:nth($co, 1);} // sad
.icon-4::before {content:"\e6f6";color:nth($co, 1);} // warn .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-6::before {content:"\e636";color:nth($cgr, 1);} // time
.icon-7::before {content:"\e623";color:nth($co, 1);} // star .icon-7::before {content:"\e623";color:nth($co, 1);} // star
.icon-8::before {content:"\e604";color:nth($cr, 1);} // mute .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);} .layer-title {width:100%;height:43px;padding:0 10px;line-height:43px;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-content {position:relative;width:100%;height:auto;min-height:50px;padding:10px; .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;} .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; .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)} &::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);}
&:active {background:nth($cp, 3)}
&:hover {
&::before {opacity:1;transform:scale(1, .8);}
}
&:active {background:nth($cp, 1)}
} }
} }
@ -76,7 +74,7 @@
/* ;alert/confirm/prompt 3类弹层 */ /* ;alert/confirm/prompt 3类弹层 */
&.type-1, &.type-1,
&.type-2, &.type-2,
&.type-3 {max-width:600px;min-width:230px;} &.type-3 {max-width:600px;min-width:300px;}
/* tips类弹层(type 5) */ /* tips类弹层(type 5) */
@ -178,9 +176,15 @@
&:active {z-index:65536;} &: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);} &.type-6 {background:rgba(0,0,0,.3);}
} }

1379
src/js/marked/index.js Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -5,9 +5,8 @@
* *
*/ */
"use strict"; 'use strict'
import 'layer/base'
define(['lib/layer/base'], function(){
function objArr(num) { function objArr(num) {
var arr = [] var arr = []
@ -21,15 +20,16 @@ define(['lib/layer/base'], function(){
return str.replace(new RegExp('^' + sign + '|' + sign + '$', 'g'), '') return str.replace(new RegExp('^' + sign + '|' + sign + '$', 'g'), '')
} }
function getOrderArr(len) { function getOrderArr(len) {
var arr = [], i = 0; var arr = [],
i = 0
while (i < len) { while (i < len) {
arr.push(i++) arr.push(i++)
} }
return arr return arr
} }
ME.addon = { const addon = {
h1: function(elem, vm) { h1: function(elem, vm) {
var offset = yua(elem).offset(), var offset = Anot(elem).offset(),
wrap = ME.selection(vm.$editor, true) || '在此输入文本', wrap = ME.selection(vm.$editor, true) || '在此输入文本',
h1ID = layer.open({ h1ID = layer.open({
type: 7, type: 7,
@ -42,15 +42,21 @@ define(['lib/layer/base'], function(){
ME.insert(vm.$editor, wrap, true) ME.insert(vm.$editor, wrap, true)
layer.close(h1ID) layer.close(h1ID)
}, },
offset: [offset.top + 37 - ME.doc.scrollTop(), 'auto', 'auto', offset.left - ME.doc.scrollLeft()], offset: [
content: '<ul class="do-meditor-h1 do-fn-noselect do-meditor-font">' offset.top + 37 - ME.doc.scrollTop(),
+ '<li :click="$insert(1)" class="h1">一级标题</li>' 'auto',
+ '<li :click="$insert(2)" class="h2">二级标题</li>' 'auto',
+ '<li :click="$insert(3)" class="h3">三级标题</li>' offset.left - ME.doc.scrollLeft()
+ '<li :click="$insert(4)" class="h4">四级标题</li>' ],
+ '<li :click="$insert(5)" class="h5">五级标题</li>' content:
+ '<li :click="$insert(6)" class="h6">六级标题</li>' '<ul class="do-meditor-h1 do-fn-noselect do-meditor-font">' +
+ '</ul>' '<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) {
@ -63,7 +69,7 @@ define(['lib/layer/base'], function(){
var wrap = ME.selection(vm.$editor) || '在此输入文本', 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) ME.insert(vm.$editor, wrap, true)
}, },
@ -71,7 +77,7 @@ define(['lib/layer/base'], function(){
var wrap = ME.selection(vm.$editor) || '在此输入文本', 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) ME.insert(vm.$editor, wrap, true)
}, },
@ -79,7 +85,7 @@ define(['lib/layer/base'], function(){
var wrap = ME.selection(vm.$editor) || '在此输入文本', 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) ME.insert(vm.$editor, wrap, true)
}, },
@ -99,7 +105,7 @@ define(['lib/layer/base'], function(){
ME.insert(vm.$editor, '\n\n---\n\n', false) ME.insert(vm.$editor, '\n\n---\n\n', false)
}, },
link: function(elem, vm) { link: function(elem, vm) {
var offset = yua(elem).offset(), var offset = Anot(elem).offset(),
wrap = ME.selection(vm.$editor) || '', wrap = ME.selection(vm.$editor) || '',
layid = layer.open({ layid = layer.open({
type: 7, type: 7,
@ -110,40 +116,49 @@ define(['lib/layer/base'], function(){
linkName: wrap, linkName: wrap,
linkTarget: 1, linkTarget: 1,
$confirm: function() { $confirm: function() {
var lvm = yua.vmodels[layid] var lvm = Anot.vmodels[layid]
if (!lvm.link || !lvm.linkName) { if (!lvm.link || !lvm.linkName) {
return layer.alert('链接文字和地址不能为空') return layer.alert('链接文字和地址不能为空')
} }
var val = '[' + lvm.linkName + '](' var val =
+ lvm.link '[' +
+ (lvm.linkTarget === 1 ? ' "target=_blank"' : '') lvm.linkName +
+ ')' '](' +
lvm.link +
(lvm.linkTarget === 1 ? ' "target=_blank"' : '') +
')'
ME.insert(vm.$editor, val, false) ME.insert(vm.$editor, val, false)
layer.close(layid) layer.close(layid)
}, },
offset: [offset.top + 37 - ME.doc.scrollTop(), 'auto', 'auto', offset.left - ME.doc.scrollLeft()], offset: [
content: '<div class="do-meditor-common do-meditor-font">' offset.top + 37 - ME.doc.scrollTop(),
+ '<section class="input"><span class="label">链接文字</span>' 'auto',
+ '<input class="txt" :duplex="linkName" />' 'auto',
+ '</section>' offset.left - ME.doc.scrollLeft()
+ '<section class="input"><span class="label">链接地址</span>' ],
+ '<input class="txt" :duplex="link"/>' content:
+ '</section>' '<div class="do-meditor-common do-meditor-font">' +
+ '<section>' '<section class="input"><span class="label">链接文字</span>' +
+ '<label><input name="link" type="radio" class="radio" :duplex-number="linkTarget" value="1"/> 新窗口打开</label>' '<input class="txt" :duplex="linkName" />' +
+ '<label><input name="link" type="radio" class="radio" :duplex-number="linkTarget" value="2"/> 本窗口打开</label>' '</section>' +
+ '</section>' '<section class="input"><span class="label">链接地址</span>' +
+ '<section>' '<input class="txt" :duplex="link"/>' +
+ '<a href="javascript:;" class="submit" :click="$confirm">确定</a>' '</section>' +
+ '</section>' '<section>' +
+ '</div>' '<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) ME.insert(vm.$editor, new Date().format(), false)
}, },
face: function(elem, vm) { face: function(elem, vm) {
var offset = yua(elem).offset(), var offset = Anot(elem).offset(),
faceid = 0, faceid = 0,
layid = layer.open({ layid = layer.open({
type: 7, type: 7,
@ -151,10 +166,16 @@ define(['lib/layer/base'], function(){
fixed: true, fixed: true,
shadeClose: true, shadeClose: true,
arr: getOrderArr(36), arr: getOrderArr(36),
offset: [offset.top + 37 - ME.doc.scrollTop(), 'auto', 'auto', offset.left - ME.doc.scrollLeft()], offset: [
content: '<ul class="do-meditor-face">' offset.top + 37 - ME.doc.scrollTop(),
+ '<li class="item" :repeat="arr" ><img :attr-src="ME.path + \'/addon/face/\' + el + \'.gif\'" :click="$insert(this.src)" /></li>' 'auto',
+ '</ul>', '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) { $insert: function(src) {
ME.insert(vm.$editor, '![](' + src + ')', false) ME.insert(vm.$editor, '![](' + src + ')', false)
layer.close(layid) layer.close(layid)
@ -162,41 +183,50 @@ define(['lib/layer/base'], function(){
}) })
}, },
table: function(elem, vm) { table: function(elem, vm) {
var offset = yua(elem).offset(); var offset = Anot(elem).offset()
layer.open({ layer.open({
type: 7, type: 7,
title: '0行 x 0列', title: '0行 x 0列',
fixed: true, fixed: true,
shadeClose: true, shadeClose: true,
offset: [offset.top + 37 - ME.doc.scrollTop(), 'auto', 'auto', offset.left - ME.doc.scrollLeft()], offset: [
matrix: objArr(10).map(function(){return objArr(10)}), offset.top + 37 - ME.doc.scrollTop(),
content: '<ul class="do-meditor-table">' 'auto',
+ '<li :repeat="matrix"><span :repeat-o="el" :class="{active: o.v}" :data="{x: $index, y: $outer.$index}"></span></li>' 'auto',
+ '</ul>', 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) { success: function(id) {
var tb = document.querySelector('.do-meditor-table'), var tb = document.querySelector('.do-meditor-table'),
_this = yua.vmodels[id], _this = Anot.vmodels[id],
lastx,lasty; lastx,
yua(tb).bind('mousemove', function(ev){ lasty
Anot(tb).bind('mousemove', function(ev) {
if (ev.target.nodeName === 'SPAN') { if (ev.target.nodeName === 'SPAN') {
var x = ev.target.dataset.x - 0, var x = ev.target.dataset.x - 0,
y = ev.target.dataset.y - 0; y = ev.target.dataset.y - 0
if (x === lastx && y === lasty) { if (x === lastx && y === lasty) {
return return
} }
lastx = x; lastx = x
lasty = y; lasty = y
_this.title = (y + 1) + '行 x ' + (x + 1) + '列' _this.title = y + 1 + '行 x ' + (x + 1) + '列'
for (var i = 0; i <= 9; i++) { for (var i = 0; i <= 9; i++) {
for (var j = 0; j <= 9; j++) { for (var j = 0; j <= 9; j++) {
_this.matrix[i][j].v = (i <= y && j <= x) ? 1 : 0 _this.matrix[i][j].v = i <= y && j <= x ? 1 : 0
} }
} }
} }
}) })
yua(tb).bind('mouseleave', function(ev){ Anot(tb).bind('mouseleave', function(ev) {
lastx = -1; lastx = -1
lasty = -1; lasty = -1
_this.title = '0行 x 0列' _this.title = '0行 x 0列'
for (var i = 0; i <= 9; i++) { for (var i = 0; i <= 9; i++) {
for (var j = 0; j <= 9; j++) { for (var j = 0; j <= 9; j++) {
@ -204,14 +234,18 @@ define(['lib/layer/base'], function(){
} }
} }
}) })
yua(tb).bind('click', function(ev){ Anot(tb).bind('click', function(ev) {
if (ev.target.nodeName === 'SPAN') { if (ev.target.nodeName === 'SPAN') {
var x = ev.target.dataset.x - 0 + 1, 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' var val =
+ ME.repeat('| -- ', x) + '|\n' '\n\n' +
+ ME.repeat(ME.repeat('| ', x) + '|\n', y) ME.repeat('| 表头 ', x) +
'|\n' +
ME.repeat('| -- ', x) +
'|\n' +
ME.repeat(ME.repeat('| ', x) + '|\n', y)
ME.insert(vm.$editor, val, false) ME.insert(vm.$editor, val, false)
layer.close(id) layer.close(id)
} }
@ -220,7 +254,7 @@ define(['lib/layer/base'], function(){
}) })
}, },
image: function(elem, vm) { image: function(elem, vm) {
var offset = yua(elem).offset(), var offset = Anot(elem).offset(),
wrap = ME.selection(vm.$editor) || '', wrap = ME.selection(vm.$editor) || '',
layid = layer.open({ layid = layer.open({
type: 7, type: 7,
@ -230,7 +264,7 @@ define(['lib/layer/base'], function(){
img: '', img: '',
imgAlt: wrap, imgAlt: wrap,
$confirm: function() { $confirm: function() {
var lvm = yua.vmodels[layid] var lvm = Anot.vmodels[layid]
if (!lvm.img || !lvm.imgAlt) { if (!lvm.img || !lvm.imgAlt) {
return layer.alert('图片描述和图片地址不能为空') return layer.alert('图片描述和图片地址不能为空')
} }
@ -239,18 +273,24 @@ define(['lib/layer/base'], function(){
ME.insert(vm.$editor, val, false) ME.insert(vm.$editor, val, false)
layer.close(layid) layer.close(layid)
}, },
offset: [offset.top + 37 - ME.doc.scrollTop(), 'auto', 'auto', offset.left - ME.doc.scrollLeft()], offset: [
content: '<div class="do-meditor-common do-meditor-font">' offset.top + 37 - ME.doc.scrollTop(),
+ '<section class="input"><span class="label">图片描述</span>' 'auto',
+ '<input class="txt" :duplex="imgAlt" />' 'auto',
+ '</section>' offset.left - ME.doc.scrollLeft()
+ '<section class="input"><span class="label">图片地址</span>' ],
+ '<input class="txt" :duplex="img"/>' content:
+ '</section>' '<div class="do-meditor-common do-meditor-font">' +
+ '<section>' '<section class="input"><span class="label">图片描述</span>' +
+ '<a href="javascript:;" class="submit" :click="$confirm">确定</a>' '<input class="txt" :duplex="imgAlt" />' +
+ '</section>' '</section>' +
+ '</div>' '<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) {
@ -258,9 +298,9 @@ define(['lib/layer/base'], function(){
}, },
inlinecode: function(elem, vm) { inlinecode: function(elem, vm) {
var wrap = ME.selection(vm.$editor) || '在此输入文本', 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) ME.insert(vm.$editor, wrap, true)
}, },
blockcode: function(elem, vm) { blockcode: function(elem, vm) {
@ -301,30 +341,32 @@ define(['lib/layer/base'], function(){
{ id: 'typescript' }, { id: 'typescript' },
{ id: 'xml' }, { id: 'xml' },
{ id: 'yaml' }, { id: 'yaml' },
{id: 'other', name: '其他语言'}, { id: 'other', name: '其他语言' }
], ],
lang: 'javascript', lang: 'javascript',
code: '', code: '',
$confirm: function() { $confirm: function() {
var lvm = yua.vmodels[layid] var lvm = Anot.vmodels[layid]
var val = '\n```' + lvm.lang + '\n' + (lvm.code || '//在此输入代码') + '\n```\n' var val =
'\n```' + lvm.lang + '\n' + (lvm.code || '//在此输入代码') + '\n```\n'
ME.insert(vm.$editor, val, false) ME.insert(vm.$editor, val, false)
layer.close(layid) layer.close(layid)
}, },
content: '<div class="do-meditor-codeblock do-meditor-font">' content:
+ '<section class="do-fn-cl"><span class="label">语言类型</span>' '<div class="do-meditor-codeblock do-meditor-font">' +
+ '<select :duplex="lang">' '<section class="do-fn-cl"><span class="label">语言类型</span>' +
+ '<option :repeat="$lang" :attr-value="el.id">{{el.name || el.id}}</option>' '<select :duplex="lang">' +
+ '</select>' '<option :repeat="$lang" :attr-value="el.id">{{el.name || el.id}}</option>' +
+ '</section>' '</select>' +
+ '<section>' '</section>' +
+ '<textarea :duplex="code" placeholder="在这里输入/粘贴代码"></textarea>' '<section>' +
+ '</section>' '<textarea :duplex="code" placeholder="在这里输入/粘贴代码"></textarea>' +
+ '<section class="do-fn-cl">' '</section>' +
+ '<a href="javascript:;" class="submit" :click="$confirm">确定</a>' '<section class="do-fn-cl">' +
+ '</section>' '<a href="javascript:;" class="submit" :click="$confirm">确定</a>' +
+ '</div>' '</section>' +
'</div>'
}) })
}, },
preview: function(elem, vm) { preview: function(elem, vm) {
@ -338,26 +380,28 @@ define(['lib/layer/base'], function(){
vm.$onFullscreen(vm.fullscreen) vm.$onFullscreen(vm.fullscreen)
}, },
about: function(elem) { about: function(elem) {
var offset = yua(elem).offset() var offset = Anot(elem).offset()
layer.open({ layer.open({
type: 7, type: 7,
title: '关于编辑器', title: '关于编辑器',
offset: [offset.top + 37 - ME.doc.scrollTop()], offset: [offset.top + 37 - ME.doc.scrollTop()],
content: '<div class="do-meditor-about do-meditor-font">' content:
+ '<pre>' '<div class="do-meditor-about do-meditor-font">' +
+ ' __ __ _____ _ _ _\n' '<pre>' +
+ '| \\/ | ____|__| (_) |_ ___ _ __\n' ' __ __ _____ _ _ _\n' +
+ '| |\\/| | _| / _` | | __/ _ \\| \'__|\n' '| \\/ | ____|__| (_) |_ ___ _ __\n' +
+ '| | | | |__| (_| | | || (_) | |\n' "| |\\/| | _| / _` | | __/ _ \\| '__|\n" +
+ '|_| |_|_____\\__,_|_|\\__\\___/|_| ' '| | | | |__| (_| | | || (_) | |\n' +
+ 'v' + ME.version + '</pre>' '|_| |_|_____\\__,_|_|\\__\\___/|_| ' +
+ '<p>开源在线Markdown编辑器</p>' 'v' +
+ '<p><a target="_blank" href="https://doui.cc/product/meditor">https://doui.cc/product/meditor</a></p>' ME.version +
+ '<p>Copyright © 2017 Yutent, The MIT License.</p>' '</pre>' +
+ '</div>' '<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

470
src/js/meditor/index.js Normal file
View File

@ -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(/&amp;/g, '&')
.replace(/&lt;/g, '<')
.replace(/&gt;/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, '&lt;script$1&gt;')
.replace(/<\/script>/g, '&lt;/script&gt;')
}
//只解析,不渲染
this.$htmlTxt = marked(txt)
}
}
})

View File

@ -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(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/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, '&lt;script$1&gt;')
.replace(/<\/script>/g, '&lt;/script&gt;')
}
//只解析,不渲染
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文本
})
})
})

View File

@ -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; .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 { .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; .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;} span:hover {background:#e5e5e5;}
.icon-pipe {width:20px;} .icon-pipe {width:20px;color:nth($cp, 3)}
.icon-pipe:hover {background:none;} .icon-pipe:hover {background:none;}
.icon-pipe::before {content:"\e62c"} .icon-pipe::before {content:"\e677"}
.icon-h1::before {content:"\e62b"} .icon-h1::before {content:"\e65c"}
.icon-bold::before {content:"\e62f"} .icon-bold::before {content:"\e66c"}
.icon-italic::before {content:"\e639"} .icon-italic::before {content:"\e670"}
.icon-through::before {content:"\e619"} .icon-through::before {content:"\e66d"}
.icon-link::before {content:"\e61c"} .icon-link::before {content:"\e667"}
.icon-inlinecode::before {content:"\e63a"} .icon-inlinecode::before {content:"\e67a"}
.icon-blockcode::before {content:"\e632"} .icon-blockcode::before {content:"\e67b"}
.icon-quote::before {content:"\e61b"} .icon-quote::before {content:"\e66a"}
.icon-hr::before {content:"\e614"} .icon-hr::before {content:"\e676"}
.icon-time::before {content:"\e636"} .icon-time::before {content:"\e675"}
.icon-face::before {content:"\e630"} .icon-face::before {content:"\e673"}
.icon-image::before {content:"\e637"} .icon-image::before {content:"\e682"}
.icon-file::before {content:"\e618"} .icon-file::before {content:"\e66b"}
.icon-preview::before {content:"\e61f"} .icon-preview::before {content:"\e67d"}
.icon-fullscreen::before {content:"\e621"} .icon-fullscreen::before {content:"\e67e"}
.icon-table::before {content:"\e617"} .icon-table::before {content:"\e65a"}
.icon-ordered::before {content:"\e638"} .icon-ordered::before {content:"\e664"}
.icon-unordered::before {content:"\e633"} .icon-unordered::before {content:"\e663"}
.icon-about::before {content:"\e700"} .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;} .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;}

View File

@ -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; .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;} &.home::after {content:"\e691";font-size:18px;}
&.prev::after {content:"\e659";font-size:18px;} &.prev::after {content:"\e67c";font-size:18px;}
&.next::after {content:"\e658";font-size:18px;} &.next::after {content:"\e66e";font-size:18px;}
&.end::after {content:"\e653";font-size:18px;} &.end::after {content:"\e693";font-size:18px;}
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1876
src/js/prism/index.js Normal file

File diff suppressed because one or more lines are too long